好的,这就是我要做的:
我有一个这样的DataFrame:
data = pd.DataFrame(
{'a' : [1,1,1,2,2,3,3,3],
'b' : [23,45,62,24,45,34,25,62],
})
我设法通过使用以下代码来计算“ a”列与“ b”列分组的平均值:
data.groupby('b', as_index=False)['a'].mean()
这导致了这样的DataFrame:
但是,我只想计算在DataFrame中多次出现的'b'值的平均值,从而得到这样的Dataframe:
我尝试通过使用以下行来做到这一点:
data.groupby('b', as_index=False).filter(lambda group: len(group)>1)['a'].mean()
但是它导致第1、2、4和7行的平均值,这显然不是我想要的。 有人可以帮我获得所需的DataFrame并告诉我在使用过滤功能时出现了什么问题吗?
谢谢!
答案 0 :(得分:3)
您可以使用data['b'].duplicated(keep=False)
进行此操作,首先创建一个布尔掩码:
>>> data[data['b'].duplicated(keep=False)].groupby('b', as_index=False)['a'].mean()
b a
0 45 1.5
1 62 2.0
data.b.duplicated(keep=False)
将所有重复出现的事件标记为True,并允许您将输出限制为这些行:
>>> data.b.duplicated(keep=False)
0 False
1 True
2 True
3 False
4 True
5 False
6 False
7 True
Name: b, dtype: bool
>>> data[data.b.duplicated(keep=False)]
a b
1 1 45
2 1 62
4 2 45
7 3 62
此解决方案可以推广到任意数目的出现吗?假设我只想为在DataFrame上出现5次以上的值计算平均值。
在这种情况下,您需要生成一个与上面的示例相同形状的布尔蒙版,但是使用的方法略有不同。
这是一种方法:
>>> vc = data['b'].map(data['b'].value_counts(sort=False))
>>> vc
0 1
1 2
2 2
3 1
4 2
5 1
6 1
7 2
Name: b, dtype: int64
这些是b
中每个元素的按元素计数。将此内容屏蔽(例如,您只希望count == 2,这与上面的示例相同,但是可以扩展为任何int):
mask = vc == 2 # or > 5, in your case
data[mask].groupby('b', as_index=False)['a'].mean()
答案 1 :(得分:1)
您非常接近:
data.groupby('b').filter(lambda g:len(g)>1).groupby('b',as_index=False).mean()
得到您想要的答案:
b a
0 45 1.5
1 62 2.0
答案 2 :(得分:1)
您可以在loc
之前通过groupby
在数据框之前进行过滤:
df = pd.DataFrame({'a' : [1,1,1,2,2,3,3,3],
'b' : [23,45,62,24,45,34,25,62]})
counts = df['b'].value_counts()
res = df.loc[df['b'].isin(counts[counts > 1].index)]\
.groupby('b', as_index=False)['a'].mean()
print(res)
b a
0 45 1.5
1 62 2.0