如何解决对剩余组中的非零值进行切片后的 Pandas groupby 平均值
嗨,考虑以下数据帧
import pandas as pd
import numpy as np
a = pd.DataFrame(np.array([[1,1,1],[1,2,0],[2,1]]),columns = ['k1','k2','k3','v'])
print(a)
k1 k2 k3 v
0 1 1 1 1
1 1 1 2 0
2 1 2 1 1
3 1 2 2 0
4 2 1 1 0
5 2 1 2 0
6 2 2 1 1
7 2 2 2 1
我想计算 v
如何相对于 k1
变化,因此我对 k1
进行分组并计算平均值。
print(a.groupby('k1').mean()['v'])
k1
1 0.5
2 0.5
但是我们可以看到,当 k2
= 1 和 k3
= 2 时,v
的值始终为 0(对于 k1
= 1 和 2)。我希望忽略这些行。因此,为了过滤 k2
和 k3
的此类组,我正在执行以下操作
b = (a.groupby(['k2','k3']).mean()['v']!=0).reset_index()
b = b[b['v']]
del b['v']
print(b)
k2 k3
0 1 1
2 2 1
3 2 2
c = a.merge(b,how='inner',on=['k2','k3'])
print(c)
k1 k2 k3 v
0 1 1 1 1
1 2 1 1 0
2 1 2 1 1
3 2 2 1 1
4 1 2 2 0
5 2 2 2 1
然后最终对 k1
进行分组平均,我得到了一个更好/可取的指标。
print(c.groupby('k1').mean()['v'])
k1
1 0.666667
2 0.666667
有没有更简单的方法来实现这个计算,因为它看起来是一种很常见的分析方法,但需要很长的操作链
解决方法
但是我们可以看到,当 k2 = 1 和 k3= 2 时,v 的值始终为 0(对于 k1 = 1 和 2)。我希望忽略这些行。
如果你检查标准错误:
(a.groupby(['k2','k3']).transform(pd.Series.std) > 0).v
0 True
1 False
2 False
3 True
4 True
5 False
6 False
7 True
Name: v,dtype: bool
它显示了 v 的行不是常量的行。你可以过滤掉这个。
,您可以使用查询方法过滤掉不需要的组合,如下所示。
import pandas as pd
import numpy as np
a = pd.DataFrame(np.array([[1,1,1],[1,2,0],[2,1]]),columns = ['k1','k2','k3','v'])
a = a.query('v != 0 or k2 == k3')
print(a.groupby('k1').mean()['v'])
结果为:
k1
1 0.666667
2 0.666667
,
基于@anky、@Shubham、@ami 和@vbn 的评论和回答——对代码的一些简化可能是
- 使用查询方法过滤 v=0 的行
- 使用transform方法而不是直接分组并稍后加入
>>> import pandas as pd
>>> import numpy as np
>>> a = pd.DataFrame(np.array([[1,'v'])
>>> print(a)
k1 k2 k3 v
0 1 1 1 1
1 1 1 2 0
2 1 2 1 1
3 1 2 2 0
4 2 1 1 0
5 2 1 2 0
6 2 2 1 1
7 2 2 2 1
>>>
>>> ## method 1
... out = a[a.groupby(['k2','k3']).transform(pd.Series.mean)['v']!=0].groupby('k1').mean()['v']
>>> print(out)
k1
1 0.666667
2 0.666667
Name: v,dtype: float64
>>>
>>> ## method 2
... out = a.merge(a.groupby(['k2','k3']).mean().query('v!=0').index.to_frame().reset_index(drop=True),on=['k2','k3']).groupby('k1')['v'].mean()
>>> print(out)
k1
1 0.666667
2 0.666667
Name: v,dtype: float64
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。