计算 R data.frame 中的子列 z 分数

Calculate sub-column-wise z scores in R data.frame

我有下面的例子data.frame

df = data.frame(a=c(rep("a",8), rep("b",5), rep("c",7), rep("d",10)), 
    b=rnorm(30, 6, 2), 
    c=rnorm(30, 12, 3.5), 
    d=rnorm(30, 8, 3)
    )

对于每一列,我想计算 a 列中定义的每个子组的 z 分数。 对我很有帮助,我现在可以使用以下方法做到这一点:

 df$b.zscore <- ave(df$b, df$a, FUN = scale)
 df$c.zscore <- ave(df$c, df$a, FUN = scale)
 df$d.zscore <- ave(df$d, df$a, FUN = scale)

但我的真实数据有更多列。是否有更优雅的方法来为 b-d 列完成此操作?也许使用 for 循环?请问我该怎么做?我希望任何人都可以提供帮助。谢谢。

您可以在列上使用 lapply :

cols <- c('b', 'c', 'd')
new_cols <- paste0(cols, '_zscore')
df[new_cols] <- lapply(df[cols], function(x) ave(x, df$a, FUN = scale))

但是,这种对多列进行操作的操作最好用 dplyr

来完成
library(dplyr)

df %>%
  group_by(a) %>%
  mutate(across(b:d, list(zscore = ~as.numeric(scale(.)))))
  #For dplyr < 1.0.0
  #mutate_at(vars(b:d), list(zscore = ~as.numeric(scale(.))))

data.table :

library(data.table)
setDT(df)[, (new_cols) := lapply(.SD, function(x) as.numeric(scale(x))), a, 
            .SDcols = cols]