标题可能有点含糊不清,让我解释一下我正在尝试做什么 这是我的数据框:
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
答案 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")