是否可以以某种方式将pandas.drop_duplicates与比较运算符一起使用,该比较运算符比较特定列中的两个对象以识别重复项?如果不是,还有什么替代方案?
这是一个可以使用它的示例:
我有一个 pandas DataFrame,其中列出了特定列中的值,我希望根据列删除重复项A
import pandas as pd
df = pd.DataFrame( {'A': [[1,2],[2,3],[1,2]]} )
print df
Run Code Online (Sandbox Code Playgroud)
给我
A
0 [1, 2]
1 [2, 3]
2 [1, 2]
Run Code Online (Sandbox Code Playgroud)
df.drop_duplicates( 'A' )
Run Code Online (Sandbox Code Playgroud)
给我一个TypeError
[...]
TypeError: type object argument after * must be a sequence, not itertools.imap
Run Code Online (Sandbox Code Playgroud)
然而我想要的结果是
A
0 [1, 2]
1 [2, 3]
Run Code Online (Sandbox Code Playgroud)
我的比较函数在这里:
def cmp(x,y):
return x==y
Run Code Online (Sandbox Code Playgroud)
但原则上它可能是别的东西,例如,
def cmp(x,y):
return x==y and len(x)>1
Run Code Online (Sandbox Code Playgroud)
如何根据比较函数有效地删除重复项?
更重要的是,如果我有更多列要分别使用不同的比较函数进行比较,我该怎么办?
IIUC,你的问题是如何使用任意函数来确定什么是重复的。为了强调这一点,假设两个列表是重复的,如果第一项的总和加上第二项的平方在每种情况下都相同
In [59]: In [118]: df = pd.DataFrame( {'A': [[1,2],[4,1],[2,3]]} )
Run Code Online (Sandbox Code Playgroud)
(请注意,第一个和第二个列表是等效的,但不相同。)
Python 通常更喜欢键函数而不是比较函数,所以这里我们需要一个函数来说明列表的键是什么;在这种情况下,它是lambda l: l[0] + l[1]**2。
我们可以使用groupby+first按键函数的值进行分组,然后取每组的第一个:
In [119]: df.groupby(df.A.apply(lambda l: l[0] + l[1]**2)).first()
Out[119]:
A
A
5 [1, 2]
11 [2, 3]
Run Code Online (Sandbox Code Playgroud)
编辑
在对问题进行进一步编辑后,这里有一些使用的示例
df = pd.DataFrame( {'A': [[1,2],[2,3],[1,2], [1], [1], [2]]} )
Run Code Online (Sandbox Code Playgroud)
那么对于
def cmp(x,y):
return x==y
Run Code Online (Sandbox Code Playgroud)
这可能是
In [158]: df.groupby(df.A.apply(tuple)).first()
Out[158]:
A
A
(1,) [1]
(1, 2) [1, 2]
(2,) [2]
(2, 3) [2, 3]
Run Code Online (Sandbox Code Playgroud)
为了
def cmp(x,y):
return x==y and len(x)>1
Run Code Online (Sandbox Code Playgroud)
这可能是
In [184]: class Key(object):
.....: def __init__(self):
.....: self._c = 0
.....: def __call__(self, l):
.....: if len(l) < 2:
.....: self._c += 1
.....: return self._c
.....: return tuple(l)
.....:
In [187]: df.groupby(df.A.apply(Key())).first()
Out[187]:
A
A
1 [1]
2 [1]
3 [2]
(1, 2) [1, 2]
(2, 3) [2, 3]
Run Code Online (Sandbox Code Playgroud)
或者,这也可以通过更简洁地完成
In [190]: df.groupby(df.A.apply(lambda l: np.random.rand() if len(l) < 2 else tuple(l))).first()
Out[190]:
A
A
0.112012068449 [2]
0.822889598152 [1]
0.842630848774 [1]
(1, 2) [1, 2]
(2, 3) [2, 3]
Run Code Online (Sandbox Code Playgroud)
但有些人不喜欢这些蒙特卡洛的东西。