【问题标题】:Group rows and calculate mean and count分组行并计算平均值和计数
【发布时间】:2017-01-05 07:11:25
【问题描述】:

这是我的数据框:

df = 
UD   QTY   GRADE   TIME_1   TIME_2
1    20    5       22.5     16.1
1    20    5       26.2     19.5
1    20    5       30.0     14.0
1    20    4       20.0     18.5
2    25    4       23.3     19.9

我需要根据UD 和QTY 的每个组合计算TIME_1 和TIME_2 的平均值。然后我想添加新列GRADE_COUNT,它将存储每组的总行数。例如,在上述数据集中,UD = 1 和 QTY = 20 定义的每组有 4 行。

结果应该是这个:

df = 

UD  QTY  MEAN_TIME_1   MEAN_TIME_2   COUNT
1   20   24.67         17.02         4
2   25   23.3          19.9          1

我编写了这段代码,它对行进行分组、计算平均值和计数值。

groupby_object = df[['UD', 'QTY', 'GRADE', 'TIME_1', 'TIME_2']].groupby(['TIME_1', 'TIME_2])

df = groupby_object.agg('mean').rename(columns = lambda x: x + ' mean').join(pd.DataFrame(groupby_object.size(),columns=['counts'])).reset_index()

但它不是计算平均时间,而是计算平均 QTY 和 GRADE,UD 列也消失了。

【问题讨论】:

  • df.groupby(['UD','QTY'])[['TIME_1','TIME_2']].mean() - 这就是你想要的吗?
  • @MaxU:请看我的更新。我发布了预期的结果。
  • @DavidZ:我正在使用最后一个版本的熊猫:0.19.1
  • @MaxU:谢谢。但它会创建两列count:一个每个TIME_1,另一个每个TIME_2。我需要每组的总行数。
  • @Dinosaurius (3 cmets up) 抱歉,这实际上是我的错误。不管怎样,你要不要按GRADE 分组?你在你的问题中都说。

标签: python pandas


【解决方案1】:

可以在同一步骤中进行所有不同类型的聚合,而无需合并或分配。 groupby.agg 允许您使用映射到所用聚合函数的列字典来执行此操作

df1 = df.groupby(['UD', 'QTY']).agg({'TIME_1': 'mean', 
                                     'TIME_2': 'mean', 
                                     'GRADE':'count'}).reset_index()

   UD  QTY  TIME_1  GRADE  TIME_2
0   1   20  24.675      4  17.025
1   2   25  23.300      1  19.900

【讨论】:

  • 最终解决方案能否仅包含我在问题中指定为预期结果的行?
  • 看起来您只是按 UD 和 QTY 分组,而不是 GRADE。你的最终数据框与你写的不匹配
  • 是的,这个解决方案比我的好很多
【解决方案2】:

DataFrame.groupby() 的参数指定应使用哪些列将行组合成组。所以如果你写

df.groupby([['TIME_1', 'TIME_2']])

然后 Pandas 将合并具有相同值的行 TIME_1 和 TIME_2。但是您想组合具有相同 UD 和 QTY 值的行。 (如果您还想使用GRADE 对行进行分组,只需在适当的地方添加即可。)所以使用

>>> g = df.groupby([['UD', 'QTY']])

然后您可以在结果对象上调用mean() 来获取组的平均值。

>>> g.mean()
        GRADE  TIME_1  TIME_2
UD QTY                       
1  20    4.75  24.675  17.025
2  25    4.00  23.300  19.900

同样,您可以致电count() 获取行数。

>>> g.count()
        GRADE  TIME_1  TIME_2
UD QTY                       
1  20       4       4       4
2  25       1       1       1

您现在可以使用pandas.concat() 将这些部分组合成一个新的DataFrame。

>>> m = g.mean()
>>> c = g.count()
>>> new_df = concat([m, c], axis=1)
>>> new_df
        TIME_1  TIME_2  GRADE
UD QTY                       
1  20   24.675  17.025      4
2  25   23.300  19.900      1

剩下的就是将 UD 和 QTY 从索引列更改为常规列,您可以使用 new_df.reset_index() 执行此操作,并根据自己的喜好更改列名,您可以通过分配一个列表来完成new_df.columns.

【讨论】:

    【解决方案3】:

    试试这个:

    In [295]: g = df.groupby(['UD','QTY'], as_index=False)
    
    In [297]: (pd.merge(g[['TIME_1','TIME_2']].mean(),
         ...:           g.size().to_frame('COUNT').reset_index(),
         ...:           on=['UD','QTY'])
         ...: )
         ...:
    Out[297]:
       UD  QTY  TIME_1  TIME_2  COUNT
    0   1   20  24.675  17.025      4
    1   2   25  23.300  19.900      1
    

    或者更好一点的:

    In [301]: g[['TIME_1','TIME_2']].mean().assign(COUNT=g.size().values)
    Out[301]:
       UD  QTY  TIME_1  TIME_2  COUNT
    0   1   20  24.675  17.025      4
    1   2   25  23.300  19.900      1
    

    【讨论】:

    • 我是否理解正确,例如,如果我不需要计算平均时间,那么我应该简单地运行g.assign(COUNT=g[['TIME_1','TIME_2']].size().values) 不包括[['TIME_1','TIME_2']].mean() 吗?
    • @Dinosaurius,我会试试这个:g.size().to_frame('COUNT').reset_index()
    • @Dinosaurius,您可能应该将Ted's solution 标记为正确的 - 它更好,更惯用
    猜你喜欢
    • 2023-03-03
    • 1970-01-01
    • 1970-01-01
    • 2021-07-07
    • 1970-01-01
    • 2016-01-10
    • 2017-06-30
    • 1970-01-01
    • 2021-12-07
    相关资源
    最近更新 更多