如何根据值计数过滤pandas DataFrame?

79

我正在使用Python处理一个包含视频游戏及其类型的pandas DataFrame。 我想从DataFrame中删除任何出现次数少于某个数字的游戏类型,但是我不知道如何处理此问题。我发现了一个相关的StackOverflow问题,但是我完全无法理解其中的解决方案(可能是因为我从未听说过R且我的函数式编程记忆最多也只有一点生疏)。

帮帮我?

5个回答

112

使用分组过滤

In [11]: df = pd.DataFrame([[1, 2], [1, 4], [5, 6]], columns=['A', 'B'])

In [12]: df
Out[12]:
   A  B
0  1  2
1  1  4
2  5  6

In [13]: df.groupby("A").filter(lambda x: len(x) > 1)
Out[13]:
   A  B
0  1  2
1  1  4

我建议阅读文档中的分离-合并部分


2
我们甚至可以按MultiIndex级别进行分组:groupby(level=...)。这正是我所需要的。 - Winand
1
这对我没用 - 我得到了以下错误,不确定该怎么处理它:“过滤函数返回了一个Series,但期望是一个标量bool” @Andy Hayden - ZakS

41

使用性能更好的解决方案,应该使用GroupBy.transformsize来计算每个组的项数,并生成与原始df相同大小的系列(Series),因此可以通过布尔索引进行过滤:

df1 = df[df.groupby("A")['A'].transform('size') > 1]

或者使用 Series.map 结合 Series.value_counts:

df1 = df[df['A'].map(df['A'].value_counts()) > 1]

5
就性能方面而言,我在一个大多数为JSON字符串数据的DataFrame上运行了针对一列ID字符串进行分组的“Series.map”解决方案以及上面提到的“groupby.filter”解决方案通过“%%timeit”的测试,并得到以下结果:Series map: 2.34 ms ± 254 µs per loopGroupby.filter: 269 ms ± 41.3 ms per loop。因此,“Series.map”解决方案要快得多。 - jlhasson
多列组合形成的Group By是什么? - quest

4

@jezael的解决方案非常有效,这里是一个基于值计数进行筛选的不同方法:

例如,如果数据集如下:

df = pd.DataFrame({'a': [1,2,3,3,1,6], 'b': [11,2,33,4,55,6]})

将计数转换并保存为字典

ount_freq = dict(df['a'].value_counts())

创建一个新列并复制目标列,将字典映射到新创建的列中。
df['count_freq'] = df['a']
df['count_freq'] = df['count_freq'].map(count_freq)

现在我们有了一个包含计数频率的新列,您可以使用这个列定义一个阈值并轻松过滤数据。

df[df.count_freq>1]

0

此外,如果想要过滤并添加“计数”列:

attr = 'A'
limit = 10
df2 = df.groupby(attr)[attr].agg(count='count')
df2 = df2.loc[df2['count'] > limit].reset_index()
print(df2)

#outputs rows with grouped 'A' count > 10 and columns ==> index, count, A

0

我可能有点晚来到这个派对,但是:

df = pd.DataFrame(df_you_have.groupby(['IdA', 'SomeOtherA'])['theA_you_want_to_count'].count())
df.reset_index(inplace=True)

这是如何创建新的数据框并进行筛选的方法...

df[df['A']>100]

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接