一次聚集多次

gather multiple times at once

假设我有一个 data.frame dat 像这个

id       X_a      X_b       Y_a      Y_b
v1 -0.012758 0.004537 -0.022725 0.005833
v2 -0.016706 0.003332 -0.006948 0.004965
v3 -0.005629 0.006972 -0.010578 0.006069

我希望它变成 "gathered"。请注意,X_aX_b 应与 Y_aY_b 一起收集。期望的结果是:

id    X_Y_type         X         Y
v1       X_Y_a -0.012758 -0.022725
v2       X_Y_a -0.016706 -0.006948
v3       X_Y_a -0.005629 -0.010578
v1       X_Y_b  0.004537  0.005833
v2       X_Y_b  0.003332  0.004965
v3       X_Y_b  0.006972  0.006069

gather() 应用两次不是我想要的:

dat %>%
  gather(X_type, X, X_a:X_b) %>%
  gather(Y_type, Y, Y_a:Y_b)

id X_type      X Y_type         Y
v1 X_a -0.012758    Y_a -0.022725
v2 X_a -0.016706    Y_a -0.006948
v3 X_a -0.005629    Y_a -0.010578
v1 X_b  0.004537    Y_a -0.022725
v2 X_b  0.003332    Y_a -0.006948
v3 X_b  0.006972    Y_a -0.010578
v1 X_a -0.012758    Y_b  0.005833
v2 X_a -0.016706    Y_b  0.004965
v3 X_a -0.005629    Y_b  0.006069
v1 X_b  0.004537    Y_b  0.005833
v2 X_b  0.003332    Y_b  0.004965
v3 X_b  0.006972    Y_b  0.006069

我想要 X_aY_aX_bY_b 的匹配,所以假语法是

dat %>%
  gather(X_type = Y_type, list(X, Y), list(X_a:X_b, Y_a:Y_b))

有什么提示吗?

使用dplyr/tidyr,一个选项是gather/spread。我们使用 key/value 参数中除 'id' 列之外的所有列将 'wide' 转换为 'long' 格式, separate 'key' 列分为两个, 通过 pasteing 子字符串 'X_Y_',使用拆分列之一和 'val'、mutate 'X_Y_type' 列从 'long' 重塑为 wide' ],并将 order 更改为 `arrange.

library(dplyr)
library(tidyr)
gather(dat, key, val, -id) %>% 
       separate(key, into=c('var1', 'X_Y_type')) %>%
       spread(var1, val) %>% 
       mutate(X_Y_type= paste0('X_Y_', X_Y_type)) %>%
       arrange(X_Y_type)
#  id X_Y_type         X         Y
#1 v1    X_Y_a -0.012758 -0.022725
#2 v2    X_Y_a -0.016706 -0.006948
#3 v3    X_Y_a -0.005629 -0.010578
#4 v1    X_Y_b  0.004537  0.005833
#5 v2    X_Y_b  0.003332  0.004965
#6 v3    X_Y_b  0.006972  0.006069

但是,这可以通过 data.table 中的 melt 来完成。它可以在 measure 参数中使用多个 patterns 来将 'wide' 转换为 'long' 格式。

library(data.table)#v1.9.6+
DT <- melt(setDT(dat), measure=patterns('^X', '^Y'), 
          value.name=c('X', 'Y'), variable.name='X_Y_type')

如果需要,可以使用 paste.

将 'X_Y_type' 列值更改为预期输出
DT[, X_Y_type := paste(names(DT)[2],
      unique(sub('.*_','', names(dat)[-1])), sep="_")[X_Y_type]]

DT
#   id   X_Y_type         X         Y
#1: v1 X_Y_type_a -0.012758 -0.022725
#2: v2 X_Y_type_a -0.016706 -0.006948
#3: v3 X_Y_type_a -0.005629 -0.010578
#4: v1 X_Y_type_b  0.004537  0.005833
#5: v2 X_Y_type_b  0.003332  0.004965
#6: v3 X_Y_type_b  0.006972  0.006069

或使用 base R

中的 reshape
reshape(dat, idvar='id', varying=2:ncol(dat), sep="_", direction='long')