pandas groupby & filter on count

随声附和 提交于 2020-07-09 12:45:26

问题


I want to capture some categorical values with an occurence above a certain threshold:

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

I want to get the categories with count > 20 in a list. Currently I'm doing:

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

Now this works, but I believe it can be done shorter: In order to refer the count column I need at least 2 aggregate functions, further more I need 1 variables & 2 lines. I was hoping something like:

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

but that yields:

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.

What is the most elegant / performing solution?


回答1:


You can make this much cleaner by just using the result of your initial groupby and indexing that:

Setup

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)

groupby with count

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

# categories
# cat1    12
# cat2    10
# cat3    21
# cat4    17
# cat5    15
# Name: amount, dtype: int64

Nice and clean indexing:

s[s > 20].index.tolist()
['cat3']



回答2:


You can use lambda express in boolean indexing:

Borrowing from @user2483203 setup:

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)

Use value_counts and boolean indexing:

df['categories'].value_counts()[lambda x: x>20].index.tolist()

Output:

['cat4', 'cat2']


来源:https://stackoverflow.com/questions/50824493/pandas-groupby-filter-on-count

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!