我有一个看起来像这样的表:
A B
1 cat
1 cat
1 dog
2 illama
2 alpaca
3 donkey
使用 A
作为密钥,我想删除重复项,以便该数据框成为:
A B
1 cat
3 donkey
1
重复三次,值 cat
发生的次数最多,因此会被记录。 2
没有多数,所以它被认为是含糊不清的并且完全删除了。 3
仍然存在,因为它没有重复。
答案 0 :(得分:7)
groupby
+ pd.Series.mode
这是使用pd.Series.mode
的两步解决方案:
# find the mode for each group
i = df.groupby('A').B.apply(pd.Series.mode).reset_index(level=1, drop=True)
# filter out groups which have more than one mode—ambiguous groups
j = i[i.groupby(level=0).transform('count') == 1].reset_index()
print(j)
A B
0 1 cat
1 3 donkey
groupby
+ <
自定义功能>
或者,定义一个计算模式的自定义函数,并使用apply
调用它。过滤逻辑包含在函数中。
def foo(x):
m = pd.Series.mode(x)
if len(m) == 1:
return m
df.groupby('A').B.apply(foo).reset_index(level=1, drop=True).reset_index()
A B
0 1 cat
1 3 donkey
答案 1 :(得分:3)
您可以使用statistics.mode
,如果不存在唯一模式,则会StatisticsError
。
from statistics import mode, StatisticsError
def moder(x):
try:
return mode(x)
except StatisticsError:
return None
res = df.groupby('A')['B'].apply(moder)\
.dropna().reset_index()
print(res)
A B
0 1 cat
1 3 donkey
效果基准
尽管所有3种方法都适合您的任务,但它们的性能略有不同。
基准测试结果:
df = pd.concat([df]*10000)
%timeit jpp(df) # 18.3 ms ± 414 µs per loop
%timeit cs1(df) # 28.1 ms ± 558 µs per loop
%timeit cs2(df) # 24.5 ms ± 595 µs per loop
基准代码:
from statistics import mode, StatisticsError
def moder(x):
try:
return mode(x)
except StatisticsError:
return None
def foo(x):
m = pd.Series.mode(x)
if len(m) == 1:
return m
def jpp(df):
return df.groupby('A')['B'].apply(moder)\
.dropna().reset_index()
def cs1(df):
i = df.groupby('A').B.apply(pd.Series.mode).reset_index(level=1, drop=True)
return i[i.groupby(level=0).transform('count') == 1].reset_index()
def cs2(df):
return df.groupby('A').B.apply(foo).reset_index(level=1, drop=True).reset_index()
答案 2 :(得分:3)
如何使用value_counts
和rank
:
df.groupby('A')['B'].apply(lambda x: x.value_counts().rank(ascending=False)).eq(1)[lambda x: x].reset_index()
输出:
A level_1 B
0 1 cat True
1 3 donkey True
使用排名方法=&#39;平均值&#39;作为选民获得多数&#34;来自value_count的结果。