Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/366.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 如何有条件地从数据帧中删除重复项_Python_Pandas_Dataframe_Duplicates - Fatal编程技术网

Python 如何有条件地从数据帧中删除重复项

Python 如何有条件地从数据帧中删除重复项,python,pandas,dataframe,duplicates,Python,Pandas,Dataframe,Duplicates,考虑以下数据帧 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],

考虑以下数据帧

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
条目的条目(我知道对于所有Dulicate,都会有
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

所有高效的一行程序都是最受欢迎的

如果目标是只删除重复的
NaN
,则需要稍微复杂一些的解决方案

首先,对
A
B
Col_1
进行排序,这样每个组的
NaN
s都会移到底部。然后用
keep=first调用
df.drop_duplicates

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
这里有一个替代方案:

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
# 0     True
# 1    False
# 2    False
# 3     True
# 4    False
# 5     True
# 6    False
# 7     True
# 8     True
…表达式
df.isnull().any(axis=1)
返回以下序列:

# 0    False
# 1    False
# 2     True
# 3     True
# 4     True
# 5     True
# 6    False
# 7    False
# 8    False
# 0     True
# 1    False
# 2    False
# 3     True
# 4    False
# 5     True
# 6    False
# 7     True
# 8     True
。。。我们将这两个表达式都用括号括起来(每当在索引操作中使用多个表达式时,Pandas语法都需要这样做),然后再次将它们用括号括起来,这样我们就可以对整个表达式求反(即,
~(…)
),如下所示:

~((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和条件Y均为真,或条件Z均为真”并带有
df[((X)和(Y))|(Z)]
,或者您可以只使用
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

也许:)但这能保证
Col_1
的非
NaN
值是保留的行吗?@mortysporty编辑。在向下投票人的辩护中,您可以选择一个示例,其中只需
df.drop_duplicates
就可以给出您不想要的答案。是的。我接受否决票:)我想你需要通过
keep=False
duplicated
,这样才能起作用。@ayhan我也这么想:)嗨。如果除了我们想要摆脱的
NaN
之外,还有其他价值,那么这会起作用吗?我们可以在
之后修正参数吗?@mortysporty是的,这基本上是正确的——不过,我应该警告一下,根据您测试该值的方式,如果您取消对条件的分组(即移除外圆括号),以便您可以执行类似
~(df.duplicated)&(df.colu 2!=5)
的操作,这可能是最简单的。如果您直接替换
df.Col_2!=5
由于两个当前条件在
~(…)
中的分组方式,在上面的一行中,它将被否定(即True变为False,反之亦然)。