使用groupby的最有效方法是并行应用筛选器,如何实现?
基本上,我在问SQL中下面这个语句的等效方式
select *
...
group by col_name
having condition
我认为这个命令有很多用途,包括条件均值、求和、条件概率等,这将使这个命令非常强大。
我需要非常好的性能,所以理想情况下,这样的命令不应该是在Python中执行多层操作的结果。
正如unutbu的评论中所提到的,groupby的过滤器相当于SQL的HAVING:
In [11]: df = pd.DataFrame([[1, 2], [1, 3], [5, 6]], columns=['A', 'B'])
In [12]: df
Out[12]:
A B
0 1 2
1 1 3
2 5 6
In [13]: g = df.groupby('A') # GROUP BY A
In [14]: g.filter(lambda x: len(x) > 1) # HAVING COUNT(*) > 1
Out[14]:
A B
0 1 2
1 1 3
您可以编写更复杂的函数(这些函数将应用于每个组),只要它们返回一个普通的布尔值:
In [15]: g.filter(lambda x: x['B'].sum() == 5)
Out[15]:
A B
0 1 2
1 1 3
注意:可能存在一个错误,即您不能编写函数来操作您已用于groupby的列...解决方法是手动groupby列,即g = df.groupby(df['A']))
。
DataFrame([[1, 2], [1, 3], [2, 5], [2, 8], [5, 6]], columns=['A', 'B']).groupby('A').filter(lambda x: len(x)>1).groupby('A').sum()
- Jeff.apply()
。https://dev59.com/wmAg5IYBdhLWcg3wm7_7#49476152 - citynormanfilter
函数会将DataFrameGroupBy对象“展平”为一个DataFrame,因此如果你想对所选的分组进行操作,你需要进行两次分组。 - undefinedSELECT * FROM df GROUP BY colA HAVING COUNT(*) > 1
df[df.groupby('colA').transform('size') > 1]
和相等的
SELECT * FROM df GROUP BY colA HAVING SUM(colB) > 5
是
df[df.groupby('colA')['colB'].transform('sum') > 5]
import perfplot
import pandas as pd
import numpy as np
def groupby_filter(df):
g = df.groupby('A')
return g.filter(lambda x: x['B'].sum() > 5)
def groupby_transform(df):
g = df.groupby('A')
return df[g['B'].transform('sum') > 5]
perfplot.plot(
kernels=[groupby_filter, groupby_transform],
n_range=[2**k for k in range(16)],
setup=lambda n: pd.DataFrame({
'A': np.random.choice(n, size=n, replace=False),
'B': np.random.randint(n, size=n)}),
xlabel='Number of groups'
)
我按州和县分组,其中最大值大于20,然后使用数据框的loc子查询结果为True
counties=df.groupby(['state','county'])['field1'].max()>20
counties=counties.loc[counties.values==True]
groupby-filter
的不错的例子(链接:https://dev59.com/YmYr5IYBdhLWcg3wucew#18357933)。我认为`filter`是pandas版本的`having条件`。 - unutbu