使用具有由另一列分组的两个参数的函数来变换每列

时间:2017-04-17 13:54:00

标签: r dplyr data-manipulation tidyr tidyverse

以下数据集代表我的情况:

library(dplyr)
df <- data_frame(
  G1 = rep(1:2, each = 10),
  G2 = rep(1:10, 2),
  C1 = rnorm(20),
  C2 = rnorm(20),
  C3 = rnorm(20),
  C4 = rnorm(20)
)

我想执行以下操作,

df %>%
  group_by(G1, G2) %>%
  mutate(
    C1 = C1 - C2,
    C2 = C2 - C2,
    C3 = C3 - C2,
    C4 = C4 - C2
  )

如果只有4列(C1,C2,C3和C4),我可以应用上述解决方案。但是,我有很多列,对于每个列,我需要执行相同的操作。是否有任何简洁而简单的解决方案可以将此问题扩展到许多列?

2 个答案:

答案 0 :(得分:2)

如果您可以在要改变的列名中找到一些共性,则可以利用dplyr::mutate_at()

df %>%
    group_by(G1, G2) %>%
    mutate_at(vars(starts_with("C")), funs(. - C2))

修改

因为mutate()按顺序操作并存储每列的结果,所以有两种方法可以解决问题。您可以使用reorder(df, everything(), C2),因此C2data.frame中的最后一个,或者添加第二行,如下所示:

set.seed(1)
library(dplyr)
df <- data_frame(
    G1 = rep(1:2, each = 10),
    G2 = rep(1:10, 2),
    C1 = rnorm(20, 0),
    C2 = rnorm(20, 1),
    C3 = rnorm(20, 10),
    C4 = rnorm(20, 100)
)


df %>%
    mutate_at(vars(starts_with("C"), -C2), funs(. - C2)) %>%
    mutate_at(vars(C2), funs(. - C2))

这只是对第一行上除C2之外的每一列进行变异。然后第二行返回并在愉快地减去其他列之后改变C2

答案 1 :(得分:2)

如何使用data.table使用.SDcols指定所需的列?

library(data.table)
cols <- colnames(df)[which(grepl("C",colnames(df)))]
dt <- setDT(df)[, lapply(.SD, function(x) x - C2), by=.(G1,G2), .SDcols = cols]