将DataFrame过滤为重复项并计算结果的分组均值

时间:2018-11-20 17:56:13

标签: python pandas dataframe pandas-groupby

好的,这就是我要做的:

我有一个这样的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:

current DataFrame

但是,我只想计算在DataFrame中多次出现的'b'值的平均值,从而得到这样的Dataframe:

Desired DataFrame

我尝试通过使用以下行来做到这一点:

data.groupby('b', as_index=False).filter(lambda group: len(group)>1)['a'].mean()

但是它导致第1、2、4和7行的平均值,这显然不是我想要的。 有人可以帮我获得所需的DataFrame并告诉我在使用过滤功能时出现了什么问题吗?

谢谢!

3 个答案:

答案 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