我有一个数据集,其中可能包含标识符appkey
的重复记录。理想情况下,重复的记录应该不存在,因此我将它们视为数据收集错误。我需要删除多次出现appkey
的所有实例。
drop_duplicates
方法在这种情况下没用(或者是吗?),因为它选择了第一个或最后一个重复项。有没有明显的成语用熊猫来实现这个目标?
答案 0 :(得分:7)
截至pandas版本0.12,我们为此filter
。它完全符合@ Andy的解决方案使用transform
的功能,但更简洁,更快一些。
df.groupby('AppKey').filter(lambda x: x.count() == 1)
窃取@Andy的例子,
In [1]: df = pd.DataFrame([[1, 2], [1, 4], [5, 6]], columns=['AppKey', 'B'])
In [2]: df.groupby('AppKey').filter(lambda x: x.count() == 1)
Out[2]:
AppKey B
2 5 6
答案 1 :(得分:6)
这是一种方法,使用带有计数的transform:
In [1]: df = pd.DataFrame([[1, 2], [1, 4], [5, 6]], columns=['AppKey', 'B'])
In [2]: df
Out[2]:
AppKey B
0 1 2
1 1 4
2 5 6
通过AppKey列进行分组并应用转换计数,意味着计算每次出现的AppKey并将计数分配给出现的那些行:
In [3]: count_appkey = df.groupby('AppKey')['AppKey'].transform('count')
In [4]: count_appkey
Out[4]:
0 2
1 2
2 1
Name: AppKey, dtype: int64
In [5]: count_appkey == 1
Out[5]:
0 False
1 False
2 True
Name: AppKey, dtype: bool
然后,您可以将其用作原始DataFrame的布尔掩码(只留下AppKey恰好出现一次的那些行):
In [6]: df[count_appkey == 1]
Out[6]:
AppKey B
2 5 6
答案 2 :(得分:2)
在pandas版本0.17中,drop_duplicates函数有一个' keep'参数可以设置为' False'保持没有重复的条目(其他选项是keep =' first'并且keep =' last')。所以,在这种情况下:
df.drop_duplicates(subset=['appkey'],keep=False)
答案 3 :(得分:1)
使用set operations的以下解决方案适合我。它比filter
解决方案明显更快,但更加冗长:
In [1]: import pandas as pd
In [2]: def dropalldups(df, key):
...: first = df.duplicated(key) # really all *but* first
...: last = df.duplicated(key, take_last=True)
...: return df.reindex(df.index - df[first | last].index)
...:
In [3]: df = pd.DataFrame([[1, 2], [1, 4], [5, 6]], columns=['AppKey', 'B'])
In [4]: dropalldups(df, 'AppKey')
Out[4]:
AppKey B
2 5 6
[1 rows x 2 columns]
In [5]: %timeit dropalldups(df, 'AppKey')
1000 loops, best of 3: 379 µs per loop
In [6]: %timeit df.groupby('AppKey').filter(lambda x: x.count() == 1)
1000 loops, best of 3: 1.57 ms per loop
在较大的数据集上,性能差异更为显着。以下是具有44k行的DataFrame的结果。 I列过滤的列是一个6个字符的字符串。有870次出现560个重复值:
In [94]: %timeit dropalldups(eq, 'id')
10 loops, best of 3: 26.1 ms per loop
In [95]: %timeit eq.groupby('id').filter(lambda x: x.count() == 1)
1 loops, best of 3: 13.1 s per loop