【问题标题】:Pandas GroupBy using another DataFrame of one-hot encodings/overlapping masksPandas GroupBy 使用另一个 DataFrame 的 one-hot 编码/重叠掩码
【发布时间】:2019-01-10 17:08:01
【问题描述】:

我有两个数据框,对列上的行和特征(或组成员资格)进行观察,例如:

> data_df

     a    b    c
A    1    2    1
B    0    1    3
C    0    0    1
D    2    1    1
E    1    1    1

> mask_df

    g1   g2
A    0    1
B    1    0
C    1    0
D    1    0
E    0    1

我想根据第二个数据帧 (mask_df) 中的二进制值(掩码)对第一个数据帧 (data_df) 中的值进行分组和聚合(按总和)。结果应如下所示(组 x 特征):

> aggr_df

     a    b    c
g1   2    2    5
g2   2    3    2

pandas 有没有办法在单个命令中使用第二个数据帧 (mask_df) 中包含的掩码对第一个数据帧 (data_df) 进行分组?

【问题讨论】:

    标签: python pandas dataframe group-by pandas-groupby


    【解决方案1】:

    请注意,即使在第一个数据帧 (data_df) 中的观察属于第二个数据帧 (mask_df) 中的多个掩码的情况下,这也将起作用。

    > pd.concat({x:data_df.mul(mask_df[x],0).sum() for x in mask_df}).unstack()
    
        a  b  c
    g1  2  2  5
    g2  2  3  2
    

    【讨论】:

    • 这个比较笼统
    • 但是,这很慢。在 sum/mean 聚合的情况下,请参阅我的答案以获得更快的解决方案。
    【解决方案2】:

    您可以使用 dotgroupby 廉价地做到这一点:

    data_df.groupby(mask_df.dot(mask_df.columns)).sum()
    
        a  b  c
    g1  2  2  5
    g2  2  3  2
    

    在哪里,

    mask_df.dot(mask_df.columns)
    
    A    g2
    B    g1
    C    g1
    D    g1
    E    g2
    dtype: object
    

    假设每一行总是有恰好一列设置为1,这很有效。

    【讨论】:

    • 我认为 dot 是用于矩阵乘法的,但我无法理解如何产生所需的结果。 (这可能是对幕后工作原理缺乏了解的原因。)
    • @Polkaguy6000 pandas dot 功能已扩展为使用字符串来做类似这样的酷事。
    • mask_df 是布尔数据框时,它似乎也可以工作
    • 不幸的是,这个(虽然速度很快)解决方案仅适用于非重叠掩码,请参阅 W-B 或我的答案以获得更通用的解决方案(在 sum/mean 聚合的情况下)。
    • @gc5 很好,感谢您指出区别。我赞成你的回答。
    【解决方案3】:

    我决定写另一个答案,因为:

    • coldspeed 的答案仅适用于 one-hot 编码
    • W-B 的答案不能轻易并行化,因为它运行在字典理解上

    在我的例子中,我注意到我可以通过使用mask_dfdata_df 的点积来获得相同的结果:

    > mask_df.T.dot(data_df)
    

    在获取平均值而不是总和的特殊情况下,这是可以实现的,将 mask_df 按每个组的数量缩放:

    > mask_df.T.dot(data_df).div(mask_df.sum(), axis=0)
    

    【讨论】:

      【解决方案4】:

      最好的方法是合并数据框。您可以先使用连接语句在索引上组合。 df_merge = data_df.merge(aggr_df, left_on=True, right_on=True)。然后您可以使用df_merge 进行分组操作。

      【讨论】:

        【解决方案5】:

        这是一种使用列表推导式的方法:

        pd.DataFrame([(data_df.T * mask_df[i]).sum(axis=1) for i in mask_df.columns], 
                     index = mask.columns)
        
            a  b  c
        g1  2  2  5
        g2  2  3  2
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2016-11-15
          • 2023-01-16
          • 2020-09-18
          • 2019-10-27
          • 1970-01-01
          • 2017-02-16
          • 2021-04-22
          相关资源
          最近更新 更多