在 R 中使用前缀作为 id 重塑宽到长

reshape wide to long using prefix as id in R

在 R 中,是否可以使用 reshape 函数将数据框从宽整形为长,同时将名称的前缀保留为 id,将后缀保留为列名?

例如,我可能有一个像这样的长数据框:

log_a_mean | b_mean | c_mean | log_a_std | b_std | c_std | log_a_N | b_N | c_N
_______________________________________________________________________________

 1         |  2     |   3    |    4      |   5   |   6   |   7     |  8  | 9

我希望将其重塑为:

id    | mean  | std   | N
_____________________________
log_a |  1    | 4     | 7
  b   |  2    | 5     | 8
  c   |  3    | 6     | 9

这正是我在当前项目中必须要做的。 我将 reshape2data.table 结合使用。 最后一个包不是必需的,但我已经习惯了它并为它编写了代码(虽然没有太大改变)。

您首先需要做的是一些字符串操作,以便将 id 与实际变量隔离开来。我们将应用的规则是来自输入 table 的变量具有 <id>_<variable> 的形式。 id 可以有下划线,但 variable 不能。基本上,我们会寻找最后一个下划线并从那里切掉。然后,你就把整个东西都投了。

这将是我们的数据集:

d=data.table(
    log_a_mean=1,
    b_mean=2,
    c_mean=3,
    log_a_std=4,
    b_std=5,
    c_std=6,
    log_a_N=7,
    b_N=8,
    c_N=9)

首先,我们将其融化:

d=melt(d,variable.factor=FALSE)

输出如下:

variable    value
log_a_mean     1
b_mean         2
... etc.

现在我们拆分变量:

splitvar=function(v){
as.data.frame(
  t(sapply(
    strsplit(v,"_",fixed=TRUE),
    function(x) c(paste(x[1:(length(x)-1)],collapse="_"),x[length(x)])
  )),stringsAsFactors=FALSE)
}

d[,c("id","variable"):=splitvar(variable)]

d 的输出现在看起来像

variable value id
mean         1 log_a
mean         2 b
... etc.

铸造它:

d=dcast.data.table(d,id~variable)

d 的输出现在是:

   id N mean std
    b 8    2   5
    c 9    3   6
log_a 7    1   4

我建议你稍微完成一下你的问题,这样你就不会那么快被否决了。这是一个有趣的问题,因为这是一个我偶然发现了几次的问题,所以它对每个人都有用处。但是,很难找到对您格式化问题的兴趣。

使用 data.table 的开发版本,即 v1.9.5, this could be done easily. You can install it by following these instructions

melt.data.table 中的这一新功能允许通过提供要连接的列索引,作为 measure.vars 参数的列表单独合并到多个列。

使用@YacineH 的 post 中的 d:

library(data.table)
# Get prefix of column names
nm1 <- unique(sub('_[^_]+$', '', names(d)))

d.m <- melt(d, measure.vars = list(1:3, 4:6, 7:9), 
              variable.name="id", value.name=c("mean", "std", "N"))
setattr(d.m$id, 'levels', nm1)
#      id mean std N
#1: log_a    1   4 7
#2:     b    2   5 8
#3:     c    3   6 9

由于 variable 列默认 returns 一个因子列,当它是一个列表时,数字从 1 到 length(measure.vars) ,我们只需将级别替换为 nm1 之后融化。


或者,您可以使用 reshape 来自 base R

#convert the 'data.table' to 'data.frame (if needed)
setDF(d)
#specify direction as 'long' and the column index in a list
#change the 'id' values to 'nm1' and rearrange the columns
d1 <- transform(reshape(d, direction='long', 
           varying=list(1:3, 4:6, 7:9))[-1], id=nm1)[c(4,1:3)]
#remove the prefix of column names
colnames(d1) <- sub('.*_', '', colnames(d1) )
row.names(d1) <- NULL
d1
#      id mean std N
#1 log_a    1   4 7
#2     b    2   5 8
#3     c    3   6 9

您可以从我的 "splitstackshape" 包中尝试 merged.stack。它需要每行一个唯一的 ID,我刚刚将其添加为 1:nrow(dt).

方法是(使用来自@YacineH 的回答的"d"):

library(splitstackshape)
merged.stack(d[, id := 1:nrow(d)],                ## Add the id if it doesn't exist
             var.stubs = c("mean", "std", "N"),   ## Specify the stubs
             sep = "var.stubs",                   ## The sep is just the stubs 
             atStart = FALSE)                     ## The stubs are not at the start
#    id .time_1 mean std N
# 1:  1      b_    2   5 8
# 2:  1      c_    3   6 9
# 3:  1  log_a_    1   4 7

使用基本的 gsub 删除尾随的“_”([, .time_1 := gsub("_$", "", .time_1)][]),您就大功告成了。