max*_*max 6 python grouping dataframe python-3.x pandas
DataFrameGroupby.filter方法过滤组,并返回DataFrame包含通过过滤器的行的组.
但是我该怎么做才能获得一个新的DataFrameGroupBy物体而不是DataFrame后过滤?
例如,假设我有DataFrame df两列A和B.我希望获得列B的每个值的列的平均值A,只要该组中至少有5行:
# pandas 0.18.0
# doesn't work because `filter` returns a DF not a GroupBy object
df.groupby('A').filter(lambda x: len(x)>=5).mean()
# works but slower and awkward to write because needs to groupby('A') twice
df.groupby('A').filter(lambda x: len(x)>=5).reset_index().groupby('A').mean()
# works but more verbose than chaining
groups = df.groupby('A')
groups.mean()[groups.size() >= 5]
Run Code Online (Sandbox Code Playgroud)
这是一些可重现的数据:
np.random.seed(0)
df = pd.DataFrame(np.random.randint(0, 10, (10, 2)), columns=list('AB'))
>>> df
A B
0 5 0
1 3 3
2 7 9
3 3 5
4 2 4
5 7 6
6 8 8
7 1 6
8 7 7
9 8 1
Run Code Online (Sandbox Code Playgroud)
一个示例过滤器应用程序,证明它可以处理数据。
gb = df.groupby('A')
>>> gb.filter(lambda group: group.A.count() >= 3)
A B
2 7 9
5 7 6
8 7 7
Run Code Online (Sandbox Code Playgroud)
以下是您的一些选择:
1)也可以先根据值个数进行过滤,然后进行分组。
vc = df.A.value_counts()
>>> df.loc[df.A.isin(vc[vc >= 2].index)].groupby('A').mean()
B
A
3 4.000000
7 7.333333
8 4.500000
Run Code Online (Sandbox Code Playgroud)
2)在过滤器之前和之后执行两次groupby:
>>> (df.groupby('A', as_index=False)
.filter(lambda group: group.A.count() >= 2)
.groupby('A')
.mean())
B
A
3 4.000000
7 7.333333
8 4.500000
Run Code Online (Sandbox Code Playgroud)
3)鉴于您的第一个 groupby 返回组,您还可以对这些组进行过滤:
d = {k: v
for k, v in df.groupby('A').groups.items()
if len(v) >= 2} # gb.groups.iteritems() for Python 2
>>> d
{3: [1, 3], 7: [2, 5, 8], 8: [6, 9]}
Run Code Online (Sandbox Code Playgroud)
这有点麻烦,但应该相对有效,因为您不需要重新组合。
>>> pd.DataFrame({col: [df.ix[d[col], 'B'].mean()] for col in d}).T.rename(columns={0: 'B'})
B
3 4.000000
7 7.333333
8 4.500000
Run Code Online (Sandbox Code Playgroud)
100k 行的时序
np.random.seed(0)
df = pd.DataFrame(np.random.randint(0, 10, (100000, 2)), columns=list('AB'))
%timeit df.groupby('A', as_index=False).filter(lambda group: group['A'].count() >= 5).groupby('A').mean()
100 loops, best of 3: 18 ms per loop
%%timeit
vc = df.A.value_counts()
df.loc[df.A.isin(vc[vc >= 2].index)].groupby('A').mean()
100 loops, best of 3: 15.7 ms per loop
Run Code Online (Sandbox Code Playgroud)