Преобразовать одну строку в две строки на основе значений двух столбцов - PullRequest
2 голосов
/ 22 сентября 2019
import pandas as pd
my_df = pd.DataFrame(columns=['b_code', 'c_code', 'name'], data = [[3401560221954, 6275442, 'name 1'], [987510, 987510, 'name 2'], [4473089, '', 'name 3'], ['', 9584362, 'name 4']])

Над фреймом данных установлен набор сэмплов.Мой фрейм данных имеет 70 столбцов.

То, что я хотел бы иметь, - это преобразовать одну строку в две строки, если в двух столбцах «b_code» и «c_code» присутствуют и отличаются значения.Я ищу вывод, как показано ниже:

    b_code            c_code   name
0   3401560221954              name 1
1                     6275442  name 1
2        987510       987510   name 2
3        4473089               name 3
4                     9584362  name 4

Большое спасибо заранее за любые рекомендации.

Ответы [ 3 ]

1 голос
/ 22 сентября 2019

Вы можете использовать group by и подать заявку для достижения этой цели.В функции применения вы можете проверить условие и разделить строку, если ваше условие соответствует, добавив новую строку



def split_row(x):
    x= x.copy()
    if (type(x.iloc[0].b_code) is int and type(x.iloc[0].c_code) is int) \
        and (x.iloc[0].b_code != x.iloc[0].c_code):
        new_row = x.copy()
        new_row.b_code=""
        x.c_code = ""
        x=x.append(new_row)

    return x


my_df.groupby(["b_code", "c_code"]).apply(split_row).reset_index(drop=True)
1 голос
/ 22 сентября 2019

Создайте логическую маску для дублированных строк с Series.ne для не равных, затем отфильтруйте оригинал и concat вместе строк с измененными кодами с DataFrame.assign и индекс для 100% правильного порядка, потому что алгоритм по умолчанию также в DataFrame.sort_index нестабилен quicksort:

mask = my_df['c_code'].ne(my_df['b_code']) & my_df['b_code'].ne('') & my_df['c_code'].ne('')

Альтернатива mask:

mask = my_df['c_code'].ne(my_df['b_code']) & my_df[['b_code','c_code']].eq('').sum(1).ne(1)

print (mask)
0     True
1    False
2    False
3    False
dtype: bool

df = my_df[mask]
print (df)
          b_code   c_code    name
0  3401560221954  6275442  name 1

df = pd.concat([df.assign(b_code = '').rename(lambda x: x + .3), 
                df.assign(c_code = '').rename(lambda x: x + .5),  
                my_df[~mask]]).sort_index().reset_index(drop=True)
print (df)
          b_code   c_code    name
0                 6275442  name 1
1  3401560221954           name 1
2         987510   987510  name 2
3        4473089           name 3
4                 9584362  name 4

Если в дублированных строках порядок не важен:

df = pd.concat([df.assign(b_code = ''), 
                df.assign(c_code = ''),  
                my_df[~mask]]).sort_index().reset_index(drop=True)
1 голос
/ 22 сентября 2019

Как насчет того, чтобы разделить фрейм данных вручную на части, которые вы хотите реплицировать, и на части, которые не нужно реплицировать, реплицировать, а затем объединить все вместе?

cond = (my_df.c_code != my_df.b_code) & (my_df.b_code != '') & (my_df.c_code != '')
repl1 = my_df[cond].copy()
repl1['b_code'] = ''
repl2 = my_df[cond].copy()
repl2['c_code'] = ''
pd.concat([my_df[~cond], repl1, repl2]).sort_index().reset_index(drop=True)


          b_code   c_code    name
0                 6275442  name 1
1  3401560221954           name 1
2         987510   987510  name 2
3        4473089           name 3
4                 9584362  name 4

Это не гарантирует порядок строк репликации,Если вы хотите гарантировать порядок, вы можете изменить индекс для одной из реплик.Таким образом, чтобы получить точно такой же порядок, как в вашем примере, вы можете сделать это за repl1 перед последней строкой кода:

repl1.index = np.arange(len(repl1)) + 0.01
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...