基于附加列优先级过滤pandas数据框中的重复项
我想从一个数据表中筛选出在X列中有重复的行。不过,如果X列中有重复的值,我希望根据另一个Y列的值来优先选择其中一个。例如:
import pandas as pd
print pd.__version__
x = pd.DataFrame([
['best', 'a', 'x'],
['worst', 'b', 'y'],
['best', 'c', 'x'],
['worst','d', 'y'],
['best','d', 'y'],
['worst','d', 'y'],
['best','d', 'z'],
['best','d', 'z'],
], columns=['a', 'b', 'c'])
print x
x.drop_duplicates(cols='c', inplace=True)
print x
a b c
0 best a x
1 worst b y
2 best c x
3 worst d y
4 best d y
5 worst d y
6 best d z
7 best d z
a b c
0 best a x
1 worst b y
6 best d z
我想优先选择在a列中值为best的重复项。这样会得到以下结果:
a b c
0 best a x
4 best d y
6 best d z
有没有人知道在pandas中怎么正确地做到这一点?有没有比单纯排序行更通用的方法,这样可以只保留重复项中的第一个出现?
3 个回答
2
根据@Paul H的做法(他在PyData邮件列表中提到,GroupBy.filter
似乎存在一个奇怪的bug,导致某些原因下y
被排除在外):
In [31]: df
Out[31]:
a b c
0 best a x
1 worst b y
2 best c x
3 best d y
4 worst d y
5 worst d y
6 best d z
In [32]: besties = pd.concat(v[v.a == 'best'] for _, v in df.groupby('c'))
In [33]: besties
Out[33]:
a b c
0 best a x
2 best c x
3 best d y
6 best d z
In [34]: res = besties.drop_duplicates(subset=['c'])
In [35]: res
Out[35]:
a b c
0 best a x
3 best d y
6 best d z
2
我觉得用两个 groupby
语句可以帮你实现你想要的效果。这里有一些稍微修改过的输入数据:
x = pd.DataFrame([
['best', 'a', 'x'],
['worst', 'b', 'y'],
['best', 'c', 'x'],
['worst','d', 'y'],
['worst','d', 'y'],
['best','d', 'y'],
['best','d', 'z'],
['best','d', 'z'],
], columns=['a', 'b', 'c'])
x.groupby(by=['c']) \
.filter(lambda g: g['a'] == 'best') \
.groupby(by=['b'], as_index=False) \
.first() \
.sort(axis=1) # the columns get out of order in the second groupby
这段代码返回的是:
b a c
0 a best x
1 c best x
2 d best z
不过,关于你的例子输入和输出,还是不太清楚具体应该怎么处理。但我觉得我们已经接近答案了。
5
我觉得一个更简单的方法是先对数据表进行排序,然后去掉重复的项,只保留第一个。这种方法很可靠(这里的'a'是一个包含两个值的字符串,但如果有更多字符串值需要排序,你可以使用一个函数把字符串转换成整数列)。
x = x.sort_values(['a']).drop_duplicates(cols='c')