【问题标题】:Subtract a two-level group mean from every observation in a data.frame从 data.frame 中的每个观察值中减去两级组平均值
【发布时间】:2017-05-22 07:25:39
【问题描述】:

我需要从组内的每个观察中减去按组计算的平均值。具有挑战性的部分是我在数据框中有一个子分组,或者两个级别:V5 和 V4。这是我的 data.frame 结构的示例:

B = as.data.frame(matrix(
c(2,2,3,3,4,3,1,5,7,6,4,5,8,9,2,3,8,4,5,0,7,5,6,7,5,3,2,
"A","A","A","A","B","B","C","C","C",
"TRUE","TRUE","TRUE","TRUE","FALSE","FALSE","FALSE","FALSE","FALSE"),
nrow=9,ncol=5))

所以我的 data.frame B 看起来像这样:

  V1 V2 V3 V4    V5
1  2  6  5  A  TRUE
2  2  4  0  A  TRUE
3  3  5  7  A  TRUE
4  3  8  5  A  TRUE
5  4  9  6  B FALSE
6  3  2  7  B FALSE
7  1  3  5  C FALSE
8  5  8  3  C FALSE
9  7  4  2  C FALSE

因此,如果我按 V5 和 V4 进行平均,我会得到一个新的 data.frame,我称之为 test,它考虑了多级分组:

test <- aggregate(. ~ B$V5+B$V4,data=B, mean)
> test
   B$V5 B$V4  V1       V2   V3 V4 V5
1  TRUE    A 2.5 4.500000 3.75  1  2
2 FALSE    B 3.5 4.000000 5.50  2  1
3 FALSE    C 4.0 3.666667 3.00  3  1

所以我正在努力的是从 data.frame B 中的原始观察中减去 data.frame test 中的两级组的平均值。直觉上,我假设会有一个 apply() 函数和某种条件语句,但它对我来说有点高级编码,我还在学习 R。

【问题讨论】:

  • 嗨,test 中的最后两列是编码因子:B 中的 V4 是 A、B 或 C 等于 1,2 和 test 中的 3。 B 中的 V5 为 TRUE/FALSE,在 test 中编码为 1 和 2。我不需要test 中的最后两列,但我需要从B 中的相应观察组中减去test 中的V1、V2 和V3 列中的数字。它是我想要做的数据的中心。

标签: r dataframe data.table dplyr


【解决方案1】:

这里是一个基于 R 的解决方案:

B <- data.frame(matrix(c(2,2,3,3,4,3,1,5,7,6,4,5,8,9,2,3,8,4,5,0,7,5,6,7,5,3,2), 9),
  V4=c("A","A","A","A","B","B","C","C","C"),
  V5=c("TRUE","TRUE","TRUE","TRUE","FALSE","FALSE","FALSE","FALSE","FALSE"))
B[1:3] <- lapply(B[1:3], function(x) x - ave(x, B$V4, B$V5, FUN=mean))
B

我使用了其他数据。在您的示例数据框中,所有列都是因子(您不能使用因子进行计算,例如mean(...))。

【讨论】:

  • 谢谢!那个也不错,很短!感谢您对我的“错误”data.frame 发表评论,请记住这个错误!
【解决方案2】:

我们可以通过data.table 做到这一点。将“data.frame”转换为“data.table”(setDT(B)),按“V4”、“V5”分组,循环遍历data.table(.SD)的子集,并得到每列的差异每个组的该列的mean

library(data.table)
setDT(B)[, lapply(.SD, function(x) x- mean(x)), by = .(V4, V5)]

或者我们可以使用dplyr

library(dplyr)
B %>%
  group_by(V4, V5) %>%
  mutate_all(funs(.- mean(.)))
# A tibble: 9 x 5
# Groups: V4, V5 [3]
#          V1    V2         V3     V4     V5
#       <dbl> <dbl>      <dbl> <fctr> <fctr>
#1 -0.5000000  0.25  0.7500000      A   TRUE
#2 -0.5000000 -1.75 -4.2500000      A   TRUE
#3  0.5000000 -0.75  2.7500000      A   TRUE
#4  0.5000000  2.25  0.7500000      A   TRUE
#5  0.5000000  3.50 -0.5000000      B  FALSE
#6 -0.5000000 -3.50  0.5000000      B  FALSE
#7 -3.3333333 -2.00  1.6666667      C  FALSE
#8  0.6666667  3.00 -0.3333333      C  FALSE
#9  2.6666667 -1.00 -1.3333333      C  FALSE

假设前 3 列是numeric

数据

B <- structure(list(V1 = c(2, 2, 3, 3, 4, 3, 1, 5, 7), V2 = c(6, 4, 
5, 8, 9, 2, 3, 8, 4), V3 = c(5, 0, 7, 5, 6, 7, 5, 3, 2), V4 = structure(c(1L, 
1L, 1L, 1L, 2L, 2L, 3L, 3L, 3L), .Label = c("A", "B", "C"), class = "factor"), 
V5 = structure(c(2L, 2L, 2L, 2L, 1L, 1L, 1L, 1L, 1L), .Label = c("FALSE", 
"TRUE"), class = "factor")), .Names = c("V1", "V2", "V3", 
"V4", "V5"), row.names = c(NA, -9L), class = "data.frame")

【讨论】:

  • 您好,代码有效(还不明白它的作用),谢谢您对语法的解释!
  • @marianess data.table 的一般格式是 dt[i, j, by]i 我们指定行索引 - 它可以是逻辑、数字等选择行,j 指定列,by 用于分组变量。最初我们用by = list(V4, V5),不是.(...)也可以用来指定分组变量
猜你喜欢
  • 2019-03-05
  • 1970-01-01
  • 1970-01-01
  • 2021-11-08
相关资源
最近更新 更多