考虑以下数据框
import pandas as pd
df = pd.DataFrame({'A' : [1, 2, 3, 3, 4, 4, 5, 6, 7],
'B' : ['a','b','c','c','d','d','e','f','g'],
'Col_1' :[np.NaN, 'A','A', np.NaN, 'B', np.NaN, 'B', np.NaN, np.NaN],
'Col_2' :[2,2,3,3,3,3,4,4,5]})
df
Out[92]:
A B Col_1 Col_2
0 1 a NaN 2
1 2 b A 2
2 3 c A 3
3 3 c NaN 3
4 4 d B 3
5 4 d NaN 3
6 5 e B 4
7 6 f NaN 4
8 7 g NaN 5
我想删除与列'A' 'B'
有关的所有重复行。我想删除具有NaN
条目的条目(我知道对于所有dulicates,将有NaN
和not - NaN
条目。最终结果应如下所示
A B Col_1 Col_2
0 1 a NaN 2
1 2 b A 2
2 3 c A 3
4 4 d B 3
6 5 e B 4
7 6 f NaN 4
8 7 g NaN 5
非常欢迎所有高效的单行
答案 0 :(得分:6)
如果目标只是删除NaN
重复项,则需要一个稍微复杂的解决方案。
首先,对A
,B
和Col_1
进行排序,以便将NaN
移到每个组的底部。然后使用df.drop_duplicates
:
keep=first
out = df.sort_values(['A', 'B', 'Col_1']).drop_duplicates(['A', 'B'], keep='first')
print(out)
A B Col_1 Col_2
0 1 a NaN 2
1 2 b A 2
2 3 c A 3
4 4 d B 3
6 5 e B 4
7 6 f NaN 4
8 7 g NaN 5
答案 1 :(得分:4)
这是另一种选择:
df[~((df[['A', 'B']].duplicated(keep=False)) & (df.isnull().any(axis=1)))]
# A B Col_1 Col_2
# 0 1 a NaN 2
# 1 2 b A 2
# 2 3 c A 3
# 4 4 d B 3
# 6 5 e B 4
# 7 6 f NaN 4
# 8 7 g NaN 5
这使用按位“not”运算符~
来否定满足作为重复行的关节条件的行(参数keep=False
导致方法对所有非唯一行计算为True )并包含至少一个空值。因此表达式df[['A', 'B']].duplicated(keep=False)
返回此系列的位置:
# 0 False
# 1 False
# 2 True
# 3 True
# 4 True
# 5 True
# 6 False
# 7 False
# 8 False
...表达式df.isnull().any(axis=1)
返回此系列:
# 0 True
# 1 False
# 2 False
# 3 True
# 4 False
# 5 True
# 6 False
# 7 True
# 8 True
...我们将两者括在括号中(每当在索引操作中使用多个表达式时都需要Pandas语法),然后将它们再次包含在括号 中,以便我们可以否定整个表达式(即{ {1}}),如下:
~( ... )
您可以通过进一步使用逻辑运算符~((df[['A','B']].duplicated(keep=False)) & (df.isnull().any(axis=1))) & (df['Col_2'] != 5)
# 0 True
# 1 True
# 2 True
# 3 False
# 4 True
# 5 False
# 6 True
# 7 True
# 8 False
和&
(“或”运算符)来构建更复杂的条件。与SQL一样,根据需要将条件与其他括号分组;例如,基于逻辑“两个条件X AND 条件Y 的过滤器为真,或条件Z 为真”与{{1} }。
答案 2 :(得分:1)
或者您可以使用first()
,使用第一个,将返回第一个notnull
值,因此原始输入的顺序并不重要。
df.groupby(['A','B']).first()
Out[180]:
Col_1 Col_2
A B
1 a NaN 2
2 b A 2
3 c A 3
4 d B 3
5 e B 4
6 f NaN 4
7 g NaN 5