在R中堆叠data.frame的子集

时间:2014-07-13 10:51:04

标签: r reshape melt

我有一个带有一个(或多个)id变量的数据集和许多具有相同结构的变量子集。我想以长格式堆叠这些子集:我的示例中有三个子集,因此最终表必须有三倍的行,并且id变量必须是三重的。

foo_data表是我在R中的数据示例:

individuals <-c("individual1","individual2","individual3")
subset1.var1 <- c("value1","value2","value3")
subset1.var2 <- c("value4","value5","value6")
subset1.var3 <- c("value7","value8","value9")

subset2.var1 <- c("value10","value11","value12")
subset2.var2 <- c("value13","value14","value15")
subset2.var3 <- c("value16","value17","value18")

subset3.var1 <- c("value19","value20","value21")
subset3.var2 <- c("value22","value23","value24")
subset3.var3 <- c("value25","value26","value27")

foo_data <-data.frame(individuals,subset1.var1,subset1.var2,subset1.var3,subset2.var1,
subset2.var2,subset2.var3,subset3.var1,subset3.var2,subset3.var3)

foo_data

这就是我想要的:

structure(list(id = structure(c(1L, 2L, 3L, 1L, 2L, 3L, 1L, 2L, 
3L), .Label = c("individual1", "individual2", "individual3"), class = "factor"), 
    var1 = structure(1:9, .Label = c("value1", "value2", "value3", 
    "value10", "value11", "value12", "value19", "value20", "value21"
    ), class = "factor"), var2 = structure(1:9, .Label = c("value4", 
    "value5", "value6", "value13", "value14", "value15", "value22", 
    "value23", "value24"), class = "factor"), var3 = structure(1:9, .Label = c("value7", 
    "value8", "value9", "value16", "value17", "value18", "value25", 
    "value26", "value27"), class = "factor")), .Names = c("id", 
"var1", "var2", "var3"), row.names = c(NA, 9L), class = "data.frame")

#                     individuals    time    var1    var2    var3
# individual1.subset1 individual1 subset1  value1  value4  value7
# individual2.subset1 individual2 subset1  value2  value5  value8
# individual3.subset1 individual3 subset1  value3  value6  value9
# individual1.subset2 individual1 subset2 value10 value13 value16
# individual2.subset2 individual2 subset2 value11 value14 value17
# individual3.subset2 individual3 subset2 value12 value15 value18
# individual1.subset3 individual1 subset3 value19 value22 value25
# individual2.subset3 individual2 subset3 value20 value23 value26
# individual3.subset3 individual3 subset3 value21 value24 value27

最明显的解决方案是计算一个循环,如下所示:

stacked_foo <- foo_data[,c(1:4)]
noms <- c("id","var1","var2","var3")
names(stacked_foo) <- noms
for (i in 2:3){
  c(1,(3*i-1):(3*(i+1)-2))
  temp <- foo_data[,c(1,(3*i-1):(3*(i+1)-2))]
  names(temp) <- noms
  stacked_foo <- rbind(stacked_foo,temp)
  print(i)
}

但是,有没有更快,更简洁的内容,内置函数如meltstack

1 个答案:

答案 0 :(得分:4)

选项1:基础R的reshape功能

这是reshape(来自基地R)的任务,但它希望您的data.frame名称格式略有不同。

试试这个:

names(foo_data) <- gsub("(.*)\\.(.*)", "\\2.\\1", names(foo_data))
names(foo_data)
#  [1] "individuals"  "var1.subset1" "var2.subset1" "var3.subset1" "var1.subset2"
#  [6] "var2.subset2" "var3.subset2" "var1.subset3" "var2.subset3" "var3.subset3"

如果你的名字是这种格式,你可以这样做:

reshape(foo_data, direction = "long", idvar = "individuals", 
        varying = 2:ncol(foo_data))
#                     individuals    time    var1    var2    var3
# individual1.subset1 individual1 subset1  value1  value4  value7
# individual2.subset1 individual2 subset1  value2  value5  value8
# individual3.subset1 individual3 subset1  value3  value6  value9
# individual1.subset2 individual1 subset2 value10 value13 value16
# individual2.subset2 individual2 subset2 value11 value14 value17
# individual3.subset2 individual3 subset2 value12 value15 value18
# individual1.subset3 individual1 subset3 value19 value22 value25
# individual2.subset3 individual2 subset3 value20 value23 value26
# individual3.subset3 individual3 subset3 value21 value24 value27

您可以使用rownames(your-new-df-name) <- NULL删除时髦的rownames。


选项2:来自“reshape2”的meltdcast

如果您想转到reshape2路线,可以尝试(假设列名称​​未已更改):

library(reshape2)
dfL <- melt(foo_data, id.vars = "individuals") ## Warning ahead, but OK
# Warning message:
# attributes are not identical across measure variables; they will be dropped 
X <- colsplit(dfL$variable, c("SUB", "VAR"), pattern = "\\.")
dcast(dfL, individuals + X$SUB ~ X$VAR, value.var = "value")
#   individuals   X$SUB    var1    var2    var3
# 1 individual1 subset1  value1  value4  value7
# 2 individual1 subset2 value10 value13 value16
# 3 individual1 subset3 value19 value22 value25
# 4 individual2 subset1  value2  value5  value8
# 5 individual2 subset2 value11 value14 value17
# 6 individual2 subset3 value20 value23 value26
# 7 individual3 subset1  value3  value6  value9
# 8 individual3 subset2 value12 value15 value18
# 9 individual3 subset3 value21 value24 value27

选项3:“tidyr”+“dplyr”

然而,人们似乎开始将tidyr + dplyr视为重塑数据的下一个重点。我还没有在所有的管道上销售,但方法是:

library(dplyr)
# devtools::install_github("hadley/tidyr")
library(tidyr)
foo_data %>%
  gather(vars, vals, subset1.var1:subset3.var3) %>%
  separate(vars, into = c("subset", "var")) %>%
  spread(var, vals)
#   individuals  subset    var1    var2    var3
# 1 individual1 subset1  value1  value4  value7
# 2 individual1 subset2 value10 value13 value16
# 3 individual1 subset3 value19 value22 value25
# 4 individual2 subset1  value2  value5  value8
# 5 individual2 subset2 value11 value14 value17
# 6 individual2 subset3 value20 value23 value26
# 7 individual3 subset1  value3  value6  value9
# 8 individual3 subset2 value12 value15 value18
# 9 individual3 subset3 value21 value24 value27
# Warning message:
# attributes are not identical across measure variables; they will be dropped