【问题标题】:Adding grouped mean values to column in data frame [duplicate]将分组平均值添加到数据框中的列[重复]
【发布时间】:2014-07-31 19:02:30
【问题描述】:

我想计算数据框中的组平均值,并在包含这些组平均值的原始数据框中创建一个新列。 (我正在做一项可重复性研究,我希望在新列中插入、单元和通道内的测量值的平均值,以便我可以将其减去并计算残差。)

我的数据:

> head(mytestdata,15)
   Insertion Measurement Unit Channel Value
1          1           1   A5      10  9.41
2          1           1   A5      11  9.51
3          1           1   A5      12 10.59
4          1           1   A5      13  9.45
5          1           2   A5      10  9.42
6          1           2   A5      11  9.03
7          1           2   A5      12 10.62
8          1           2   A5      13  9.39
9          1           3   A5      10  9.38
10         1           3   A5      11  9.87
11         1           3   A5      12 11.34
12         1           3   A5      13  9.59
13         2           1   A5      10 12.10
14         2           1   A5      11 11.28
15         2           1   A5      12 12.95

具体来说,我想计算每个插入、单元和通道的平均值,并将其作为平均值添加到数据框中。然后从 Value 中减去 meanValue 得到 Residual。

应该是这样的:

   Insertion Measurement Unit Channel Value meanValue
1          1           1   40      10 11.79     11.56
2          1           1   40      11 11.01     11.38
3          1           1   40      12 10.86     11.19
4          1           1   40      13 10.29     10.91
5          1           2   40      10 11.47     11.56
6          1           2   40      11 11.84     11.38
7          1           2   40      12 11.39     11.19
8          1           2   40      13 11.25     10.91
9          1           3   40      10 11.42     11.56
10         1           3   40      11 11.28     11.38
11         1           3   40      12 11.31     11.19
12         1           3   40      13 11.18     10.91
13         2           1   40      10 10.97     11.55
14         2           1   40      11 11.78     11.87
15         2           1   40      12 11.48     11.25

我知道如何使用 by、aggregate 等方法获取组,这可以让我获得第二个列表或表格,其中包含其中的值。我也相信我可以使用一些复杂的循环程序得到我想要的东西,但我希望在一个优雅的单行或两行解决方案中将它们塞回同一个数据帧中,我认为必须有一个这样做的方法,但经过几天的搜索,我没有找到它。我不想要繁琐的解决方案,因为我希望它在我扩展到更多数据时也能正常工作。

【问题讨论】:

  • 就行数和列数而言,您的实际数据大概有多大?

标签: r dataframe aggregate


【解决方案1】:

你可以使用ave来计算groupmeans:

df$MeanValue <- with(df, ave(Value, Insertion, Unit, Channel, FUN = mean))

然后计算残差:

df$Residual <- df$Value - df$MeanValue
df
#   Insertion Measurement Unit Channel Value MeanValue     Residual
#1          1           1   A5      10  9.41  9.403333  0.006666667
#2          1           1   A5      11  9.51  9.470000  0.040000000
#3          1           1   A5      12 10.59 10.850000 -0.260000000
#4          1           1   A5      13  9.45  9.476667 -0.026666667
#5          1           2   A5      10  9.42  9.403333  0.016666667
#6          1           2   A5      11  9.03  9.470000 -0.440000000
#7          1           2   A5      12 10.62 10.850000 -0.230000000
#8          1           2   A5      13  9.39  9.476667 -0.086666667
#9          1           3   A5      10  9.38  9.403333 -0.023333333
#10         1           3   A5      11  9.87  9.470000  0.400000000
#11         1           3   A5      12 11.34 10.850000  0.490000000
#12         1           3   A5      13  9.59  9.476667  0.113333333
#13         2           1   A5      10 12.10 12.100000  0.000000000
#14         2           1   A5      11 11.28 11.280000  0.000000000
#15         2           1   A5      12 12.95 12.950000  0.000000000

或者你可以使用dplyr

library(dplyr)

df %>% group_by(Insertion, Unit, Channel) %>% mutate(MeanValue = mean(Value), Residual = Value - MeanValue)

【讨论】:

  • 第一个可以写成:transform(df, MeanValue = ave(Value, Insertion, Unit, Channel)).
【解决方案2】:

使用data.table

library(data.table)
setDT(mytestdata)[, c("MeanValue", "Residual") := {m= mean(Value);list(m, Value-m)}, by=list(Insertion, Unit, Channel)]

mytestdata

#        Insertion Measurement Unit Channel Value MeanValue     Residual
#       1:         1           1   A5      10  9.41  9.403333  0.006666667
#       2:         1           1   A5      11  9.51  9.470000  0.040000000
#       3:         1           1   A5      12 10.59 10.850000 -0.260000000
#       4:         1           1   A5      13  9.45  9.476667 -0.026666667
#       5:         1           2   A5      10  9.42  9.403333  0.016666667
#       6:         1           2   A5      11  9.03  9.470000 -0.440000000
#       7:         1           2   A5      12 10.62 10.850000 -0.230000000
#       8:         1           2   A5      13  9.39  9.476667 -0.086666667
#       9:         1           3   A5      10  9.38  9.403333 -0.023333333
#      10:         1           3   A5      11  9.87  9.470000  0.400000000
#      11:         1           3   A5      12 11.34 10.850000  0.490000000
#      12:         1           3   A5      13  9.59  9.476667  0.113333333
#      13:         2           1   A5      10 12.10 12.100000  0.000000000
#      14:         2           1   A5      11 11.28 11.280000  0.000000000
#      15:         2           1   A5      12 12.95 12.950000  0.000000000

【讨论】:

  • @Arun,谢谢,我做了一个微基准测试,似乎 dplyr 和 data.table 都非常接近。还有其他更快的品种吗?
  • 在这个数据上,任何基准测试真的毫无意义.. :)。我会尝试对大约 2000 万行进行基准测试,具有不同的组大小,例如:总共 1000 个组、10000 个、100000 个、100 万个组。你会看到 data.table 在哪里以及如何扩展!
  • 阿克伦,here you go。你可以玩弄它..
  • @Arun,谢谢。看起来 data.table 在所有比较中都击败了 dplyr,尤其是当组变得更大时:-)
  • @akrun,你是怎么想到这部分的:{m= mean(Value);list(m, Value-m)} 有没有你在上面看到或自己想到的文档?
猜你喜欢
  • 1970-01-01
  • 2021-03-27
  • 1970-01-01
  • 2021-06-07
  • 1970-01-01
  • 1970-01-01
  • 2020-10-28
  • 1970-01-01
  • 2020-12-26
相关资源
最近更新 更多