【问题标题】:Pandas Dataframe: get average of first rows of each subgroup within a groupPandas Dataframe:获取组内每个子组的第一行的平均值
【发布时间】:2023-03-12 18:25:01
【问题描述】:

我有一个如下所示的 pandas 数据框:

df = pd.DataFrame({'Person_ID': [1,1,1,1,1,1,2,2,2,3,3,3,3],
                  'Item_ID': [1,1,2,4,4,4,2,3,3,1,2,2,2],
                   'Value': [1,4,6,5,8,7,3,2,9,8,4,1,2]})

我想按 person_id 和 item_id 分组,然后得到第一行的平均值。例如:Person_ID 1 与 'Item_ID's 1,2 和 4 “关联”。此 Person_ID 和这些组的第一个条目的值分别是 1,6 和 5。平均为 4。

    Person_ID   Item_ID Value
0   1   1   1
1   1   1   4
2   1   2   6
3   1   4   5
4   1   4   8
5   1   4   7
6   2   2   3
7   2   3   2
8   2   3   9
9   3   1   8
10  3   2   4
11  3   2   1
12  3   2   2

期望的结果:

Person_ID Average_value_first_entries
1   4
2   2.5
3   6

我注意到这个问题很相似,但是这个问题的一个更复杂的版本: Pandas dataframe get first row of each group 在这种情况下,我不想按一个“id”分组,而是按两个“id”分组并取平均值。

我尝试了以下方法:

df.groupby(['Person_ID', 'Item_ID']).first()['Value']

但是,这会返回每个“第一个”条目,而不是平均值。

Person_ID  Item_ID
1          1          1
           2          6
           4          5
2          2          3
           3          2
3          1          8
           2          4
Name: Value, dtype: int64

任何帮助将不胜感激。我将特别感谢“计算高效”(时间)解决方案,因为真实数据集包含 120 万行。

【问题讨论】:

    标签: python pandas pandas-groupby


    【解决方案1】:

    找出Person_IDItem_ID 的每组first 行后,您需要再次对Person_ID 进行分组以求均值。像这样:

    In [1312]: d = df.groupby(['Person_ID','Item_ID'], as_index=False).head(1)
    
    In [1315]: d.groupby('Person_ID', as_index=False)['Value'].mean()
    Out[1315]: 
       Person_ID  Value
    0          1    4.0
    1          2    2.5
    2          3    6.0
    

    按照@Datanovice 的建议,或者在一行中:

    In [1320]: df.groupby(['Person_ID','Item_ID']).first().groupby(level=0)['Value'].mean().to_frame().reset_index()
    Out[1320]: 
       Person_ID  Value
    0          1    4.0
    1          2    2.5
    2          3    6.0
    

    【讨论】:

      【解决方案2】:

      我们可以drop_duplicates

      df.drop_duplicates(['Person_ID','Item_ID']).groupby(['Person_ID']).Value.mean()
      Person_ID
      1    4.0
      2    2.5
      3    6.0
      Name: Value, dtype: float64
      

      【讨论】:

        【解决方案3】:

        我们可以将groupbyunstack 结合起来

        (df.groupby(['Person_ID','Item_ID'])
         .first()
         .unstack()
         .mean(1)
         .reset_index(name='Average_value_first_entries')
          )
        
            Person_ID   Average_value_first_entries
        0       1               4.0
        1       2               2.5
        2       3               6.0
        

        【讨论】:

        • 虽然此代码包含重命名“输出列”的行很有用,但我发现与其他解决方案相比,这种方法的鲁棒性稍差。在实际数据框中,我有许多其他列(与此问题无关);需要调整上面的代码以选择正确的 ('Value') 列;例如:df[['Person_ID','Item_ID', 'Value']].groupby(['Person_ID','Item_ID']).first().unstack().mean(1).reset_index(name='Average_value_first_entries')
        猜你喜欢
        • 2020-03-09
        • 2019-03-24
        • 2014-09-23
        • 2013-11-28
        • 2018-11-21
        • 1970-01-01
        • 1970-01-01
        • 2019-01-14
        • 2020-11-14
        相关资源
        最近更新 更多