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
答案 0 :(得分:1)
如何将数据帧手动划分为要复制的部分和不复制的部分,然后再将所有内容重新连接在一起。
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
答案 1 :(得分:1)
您可以使用group by并申请实现此目的。在Apply功能中,您可以通过添加新行来检查条件并在条件匹配时拆分行
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)
答案 2 :(得分:1)
为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)