pandas groupby & filter on count

dr *_*rry 3 python group-by pandas

我想捕获一些发生在某个阈值以上的分类值:

df:
ticket_id,  category,  amount --> some more columns
1020        cat1       1000
1022        cat1       55
1023        cat1       12291
1120        cat2       140
1121        cat3       1250 
^
|
|
Way more rows with mostly (1020) cat5, (98) cat1, cat3, cat4 and no cat2.

>>>> df.groupby('category')['amount'].count()
category
cat1       100
cat2       1
cat3       6
cat4       2
cat5       1020
Run Code Online (Sandbox Code Playgroud)

我想在列表中获取计数 > 20 的类别。目前我正在做:

>>>> t = test.groupby('disposition')['fine_amount'].agg(['count','mean'])
>>>> t[t['count']>10].index.values
array(['cat1','cat5'])
Run Code Online (Sandbox Code Playgroud)

现在这可行,但我相信它可以做得更短:为了引用count column我至少需要 2 个聚合函数,我还需要 1 个变量和 2 行。我希望是这样的:

>>>> groupby('category')['amount'].apply(lambda x: x.count() > 10)
Run Code Online (Sandbox Code Playgroud)

但这会产生:

cat1    100   True
etc

>>>> groupby('category')['amount'].apply(lambda x: x[x.count() > 10])
Fails completely

>>>> groupby('category')['amount'].count().nlargest(2)
gives the correct list but in this case because I know there are 2 elements.
Run Code Online (Sandbox Code Playgroud)

什么是最优雅/性能最好的解决方案?

Sco*_*ton 6

您可以在布尔索引中使用 lambda express:

借用 @user2483203 设置:

np.random.seed(123)
categories = ['cat1', 'cat2', 'cat3', 'cat4', 'cat5']
dct = {'categories': [np.random.choice(categories) for i in range(100)], 'amount': [np.random.randint(1, 10) for _ in range(100)]}
df = pd.DataFrame(dct)
Run Code Online (Sandbox Code Playgroud)

使用value_counts和布尔索引:

df['categories'].value_counts()[lambda x: x>20].index.tolist()
Run Code Online (Sandbox Code Playgroud)

输出:

['cat4', 'cat2']
Run Code Online (Sandbox Code Playgroud)


use*_*203 5

您可以通过使用初始 groupby 的结果并索引以下内容来使这一点更清晰:

设置

categories = ['cat1', 'cat2', 'cat3', 'cat4', 'cat5']
dct = {'categories': [random.choice(categories) for i in range(75)], 'amount': [random.randint(1, 10) for _ in range(75)]}
df = pd.DataFrame(dct)
Run Code Online (Sandbox Code Playgroud)

groupbycount

s = df.groupby('categories').amount.count()

# categories
# cat1    12
# cat2    10
# cat3    21
# cat4    17
# cat5    15
# Name: amount, dtype: int64
Run Code Online (Sandbox Code Playgroud)

漂亮干净的索引:

s[s > 20].index.tolist()
['cat3']
Run Code Online (Sandbox Code Playgroud)