我正在寻找一种更优雅的方法,通过使用melt(reshape2)或reshape函数来重塑我的数据框。
假设我有一个像这样的简单数据框:
d<-data.frame("PID"=factor(c(1,1,1,2,2,2)),
"Cue1"=factor(c(1,2,3,1,2,3)),
"Cue2"=factor(c(5,5,5,5,5,5)))
我想将第二和第三列转换为一个长列。我的代码可以使用,但我正在寻找一种更优雅的方式:
d1<-data.frame("trigger"=as.vector(t(d[,c(2:3)])))
d1$PID<-factor(rep(c(1,2),each=6))
重要的是两个因子的水平数不同(Cue1有3,Cue2有1个水平)。我上面的代码给了我一个看起来像这样的新列(这实际上就是我想要的):
trigger
1
5
2
5
3
5
...
不幸的是,互联网上关于重塑的大多数例子讨论了以下(在我的例子中,非首选)示例:
trigger
1
2
3
1
2
3
...
但我需要前者。
提前感谢您的建议。
答案 0 :(得分:3)
最简单的方法是使用melt
。这与您的初始数据框(d1
)相同,除非触发的确切顺序很重要。
library(reshape2)
d2 <- melt(d, id="PID", value.name="trigger")[,c(3,1)]
> d2
trigger PID
1 1 1
2 2 1
3 3 1
4 1 2
5 2 2
6 3 2
7 5 1
8 5 1
9 5 1
10 5 2
11 5 2
12 5 2
如果您喜欢使用base
功能,还可以使用reshape
d3 <- reshape(d, direction="long",
varying=list(names(d)[2:3]),
v.names="trigger",
idvar="PID",
new.row.names=seq(12))[,c(3,1)]
通过按触发器排序
,您可以看到它们是相同的> d2[order(d2$trigger),]
trigger PID
1 1 1
4 1 2
2 2 1
5 2 2
3 3 1
6 3 2
7 5 1
8 5 1
9 5 1
10 5 2
11 5 2
12 5 2
> d1[order(d1$trigger),]
trigger PID
1 1 1
7 1 2
3 2 1
9 2 2
5 3 1
11 3 2
2 5 1
4 5 1
6 5 1
8 5 2
10 5 2
12 5 2
答案 1 :(得分:2)
我认为“优雅”是主观的,但如果您正在寻找替代方案,您可以从我的“splitstackshape”包中考虑merged.stack
。但是,为了使merged.stack
正常工作,您的ID变量必须是唯一的。为此,您可以使用getanID
(也来自“splitstackshape”):
library(splitstackshape)
packageVersion("splitstackshape")
# [1] ‘1.4.2’
merged.stack(getanID(d, "PID"), var.stubs = "Cue",
sep = "var.stubs")[, c("PID", "Cue"), with = FALSE]
# PID Cue
# 1: 1 1
# 2: 1 5
# 3: 1 2
# 4: 1 5
# 5: 1 3
# 6: 1 5
# 7: 2 1
# 8: 2 5
# 9: 2 2
# 10: 2 5
# 11: 2 3
# 12: 2 5
## factor levels retained as desired
str(.Last.value)
# Classes ‘data.table’ and 'data.frame': 12 obs. of 2 variables:
# $ PID: Factor w/ 2 levels "1","2": 1 1 1 1 1 1 2 2 2 2 ...
# $ Cue: Factor w/ 4 levels "1","2","3","5": 1 4 2 4 3 4 1 4 2 4 ...
# - attr(*, "sorted")= chr "PID"
# - attr(*, ".internal.selfref")=<externalptr>
默认情况下,如果只是这样做,这种方法会创建一些额外的列:
merged.stack(getanID(d, "PID"), var.stubs = "Cue", sep = "var.stubs")
两个额外的列将是:
.id
,由getanID
创建。此列与“PID”列组合时将创建唯一ID。 .time_1
,这是“堆叠”步骤的结果,用于指示值来自哪个“Cue”列(在这种情况下,在1和2之间循环以表示“Cue1”和“Cue2”) 代码中标有[, c("PID", "Cue"), with = FALSE]
的部分意味着只向我们展示这两列(因为您似乎只对它感兴趣)。
答案 2 :(得分:1)
如果您只是在寻找使用熔体的单线,下面是一种方法(保留所需的订单):
# assume DF is your data frame
DF_new = data.frame(trigger = melt(t(DF[,2:3]))[,3], PID = rep(DF[,1], each=2))
DF_new
# trigger PID
# 1 1 1
# 2 5 1
# 3 2 1
# 4 5 1
# 5 3 1
# 6 5 1
# 7 1 2
# 8 5 2
# 9 2 2
# 10 5 2
# 11 3 2
# 12 5 2