使用多个变量将数据重新整形为长格式作为measure.vars

时间:2015-03-04 16:23:32

标签: r

标题可能有点含糊不清,让我解释一下我正在尝试做什么 这是我的数据框:

Person<-c("Andrew","John","Mike")
Age<-c(25,34,21)
ColA_1<-c(1,5,7)
ColA_2<-c(5,0,9)
ColA_3<-c(4,4,1)
ColB_1<-c(16,55,37)
ColB_2<-c(25,14,39)
ColB_3<-c(43,64,31)

df<-data.frame(Person=Person,Age=Age,
    ColA_1=ColA_1,
    ColA_2=ColA_2,
    ColA_3=ColA_3,
    ColB_1=ColB_1,
    ColB_2=ColB_2,
    ColB_3=ColB_3)

我想要实现的是长格式的新数据框,列A(ColB_1,ColB_2,ColB_3)位于列A下方,同时复制Person和Age的值。在SPSS中,这相当于VARSTOCASES。输出数据框将有6列:两个用于Person和Age,三个用于折叠的A和B列,另一个用于指示行是否参考A或B数据。

我已经使用{reshape2}包中的 melt 函数进行了干预,但它似乎只能将数据汇总到一列而不是三列。我唯一的解决方案是创建两个数据帧,首先是A列,第二个是B,rbind()是一起。但是,我需要为一个非常复杂的数据集实现这一点,我希望有一个更简单,更优雅的解决方案。

预期结果是:

  Person Age Index Col_1 Col_2 Col_3
1 Andrew  25     A     1     5     4
2   John  34     A     5     0     4
3   Mike  21     A     7     9     1
4 Andrew  25     B    16    25    43
5   John  34     B    55    14    64
6   Mike  21     B    37    39    31

2 个答案:

答案 0 :(得分:4)

使用data.table的devel版本,即v1.9.5,可以使用melt完成此操作。您可以按照these instructions安装它。

  library(data.table) #data.table_1.9.5
  dM <- melt(setDT(df), measure=list(c(3,6), c(4,7), c(5,8)), 
         value.name=c('Col_1', 'Col_2', 'Col_3'),
          variable.name='Index')[, Index:=LETTERS[Index]][]
  dM
  #   Person Age Index Col_1 Col_2 Col_3
  #1: Andrew  25     A     1     5     4
  #2:   John  34     A     5     0     4
  #3:   Mike  21     A     7     9     1
  #4: Andrew  25     B    16    25    43
  #5:   John  34     B    55    14    64
  #6:   Mike  21     B    37    39    31

或者您可以使用merged.stack

中的splitstackshape
  library(splitstackshape)
  library(data.table)
  setnames(merged.stack(df, var.stubs=c('1', '2', '3'), 
      sep='var.stubs', atStart=FALSE)[, .time_1:= substr(.time_1,4,4)], 
     3:6, c('Index', paste0("Col_",1:3)))[order(Index)]
 #   Person Age Index Col_1 Col_2 Col_3
 #1: Andrew  25     A     1     5     4
 #2:   John  34     A     5     0     4
 #3:   Mike  21     A     7     9     1
 #4: Andrew  25     B    16    25    43
 #5:   John  34     B    55    14    64
 #6:   Mike  21     B    37    39    31

答案 1 :(得分:2)

reshape功能在这里很好。

reshape(df, varying=list(c(3,6), c(4,7), c(5,8)), 
            times=c("A","B"), v.names=paste0("Col_",1:3), direction="long")

数据

df <- 
structure(list(Person = structure(1:3, .Label = c("Andrew", "John", 
"Mike"), class = "factor"), Age = c(25, 34, 21), ColA_1 = c(1, 
5, 7), ColA_2 = c(5, 0, 9), ColA_3 = c(4, 4, 1), ColB_1 = c(16, 
55, 37), ColB_2 = c(25, 14, 39), ColB_3 = c(43, 64, 31)), .Names = c("Person", 
"Age", "ColA_1", "ColA_2", "ColA_3", "ColB_1", "ColB_2", "ColB_3"
), row.names = c(NA, -3L), class = "data.frame")