【问题标题】:Filter DataFrame to Duplicated Items and Compute Groupwise Means on Result将 DataFrame 过滤为重复项并根据结果计算 Groupwise 均值
【发布时间】:2018-11-20 17:56:13
【问题描述】:

好的,这就是我想要做的:

我有一个这样的数据框:

data = pd.DataFrame(
{'a' : [1,1,1,2,2,3,3,3],
 'b' : [23,45,62,24,45,34,25,62],
 })

我设法使用以下代码计算了按列“b”分组的“a”列的平均值:

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 并告诉我我在使用过滤器功能时遇到了什么问题吗?

谢谢!

【问题讨论】:

    标签: python pandas dataframe pandas-groupby


    【解决方案1】:

    重复分组

    您可以先使用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()
    

    【讨论】:

    • 这是一个非常好的方法!
    【解决方案2】:

    您可以在loc before 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
    

    【讨论】:

      【解决方案3】:

      你已经很接近了:

      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
      

      【讨论】:

      • 您愿意解释一下为什么使用 groupby 两次会奏效吗?
      • 第一个 group by 与 filter 相结合会产生“b”出现多次的记录。在缩减的子集上,我们可以对“b”进行分组,为每个“b”组生成“a”的平均值。
      猜你喜欢
      • 2019-06-19
      • 1970-01-01
      • 2015-01-04
      • 2019-01-03
      • 2016-04-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多