Pandas:填充行并去重,但保留不同值
我会尽量用简单明了的例子来解释。
df_old
user, col1,col2,col3
a , X , ,
a , , Y ,
a , , , 6
b , A , ,
b , , B , C
b , , D ,
这个数据表是按照 user
排序的。我想填补空白并去掉重复的记录,所以对于用户 a,我希望最终的数据表中只保留一行。
我在处理像用户 b 这样的情况时遇到了困难。因为用户 b 在 col2 中有两个不同的值,所以我希望最终的数据表中能有两行不同的记录:
df_new
user, col1,col2,col3
a , X , Y , 6
b , A , B , C
b , A , D , C
请注意,我希望这些行是“一致”的,这样 B 和 C 就能保持在同一个索引位置。
非常感谢任何帮助!
2 个回答
2
你可以先用 ffill
方法填充缺失值,然后再用 dropna
方法去掉那些全是缺失值的行:
df.groupby('user', group_keys=False).apply(lambda g: g.ffill()).dropna(how='any')
输出结果:
user col1 col2 col3
2 a X Y 6
4 b A B C
5 b A D C
另外,如果你不想填充缺失值,可以使用 groupby.transform
方法把非缺失值向上移动,然后再用 dropna
方法去掉那些全是缺失值的行:
out = (df.set_index('user')
.groupby(level=0)
.transform(lambda s: s.sort_values(key=lambda x: x.isna(),
kind='stable').values)
.dropna(how='all').reset_index()
)
输出结果:
user col1 col2 col3
0 a X Y 6
1 b A B C
2 b NaN D NaN
使用的输入数据:
df = pd.DataFrame({'user': ['a', 'a', 'a', 'b', 'b', 'b'],
'col1': ['X', None, None, 'A', None, None],
'col2': [None, 'Y', None, None, 'B', 'D'],
'col3': [None, None, '6', None, 'C', None]})
3
使用 GroupBy.transform
方法,可以通过 Series.mask
和 Series.duplicated
来处理重复的 NaN
值。这个过程是先按非 NaN
值排序,然后处理缺失值,最后在每个用户组中去掉重复项。
out = (df.set_index('user')
.groupby('user')
.transform(lambda x: x.mask(x.duplicated()).sort_values(key=pd.isna).ffill())
.reset_index()
.drop_duplicates(ignore_index=True)
)
print (out)
user col1 col2 col3
0 a X Y 6
1 b A B C
2 b A D C
编辑:如果需要每一行的缺失值,并且至少有一个非缺失值的话,可以省略 ffill
,而是使用 DataFrame.dropna
方法,并设置 axis='all'
参数。
out = (df.set_index('user')
.groupby('user')
.transform(lambda x: x.mask(x.duplicated()).sort_values(key=pd.isna))
.dropna(how='all')
.reset_index()
)
print (out)
user col1 col2 col3
0 a X Y 6
1 b A B C
2 b NaN D NaN