使用Reforme()或melt()将数据帧从宽数据转换为长数据的更优雅的方式

使用Reforme()或melt()将数据帧从宽数据转换为长数据的更优雅的方式,r,reshape,R,Reshape,我正在寻找一种更优雅的方式,通过使用melt(Reforme2)或Reformate函数来重塑我的数据帧 假设我有一个简单的数据框,如下所示: 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))) 不幸的是,互联网上关于重塑的大多数示例都讨论了以下示例(在我的案例中是非首选示例

我正在寻找一种更优雅的方式,通过使用melt(Reforme2)或Reformate函数来重塑我的数据帧

假设我有一个简单的数据框,如下所示:

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)))
不幸的是,互联网上关于重塑的大多数示例都讨论了以下示例(在我的案例中是非首选示例):

但我需要前一个


提前感谢您的建议。

最简单的方法是使用
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
通过按触发器排序,您可以看到它们都是相同的

> 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

最简单的方法是使用
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
通过按触发器排序,您可以看到它们都是相同的

> 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

如果您只是在寻找使用melt的单层衬里,以下是一种方法(保留所需的订单):


如果您只是在寻找使用melt的单层衬里,以下是一种方法(保留所需的订单):

我认为“优雅”是主观的,但是如果你在寻找另一种选择,你可以从我的“SPLITSTACKFILE”包中考虑<代码>合并。但是,为了使

merged.stack
正常工作,您的ID变量必须是唯一的。为此,您可以使用
getanID
(也可以从“splitstackshape”中):

另外两列将是:

  • .id
    ,由
    getanID
    创建。此列与“PID”列组合时将创建唯一的ID
  • .time\u 1
    ,它是“叠加”步骤的结果,指示值来自哪个“提示”列(在本例中,在1和2之间循环表示“提示1”和“提示2”)
<代码>读取代码< >、C(“PID”、“提示”)、“使用= false”/代码>意味着只显示这两个列(因为这就是所有您感兴趣的)。

我认为“优雅”是主观的,但是如果您在寻找替代方案,可以从“SPLITSTACKFILE”包中考虑<代码>合并。但是,为了使
merged.stack
正常工作,您的ID变量必须是唯一的。为此,您可以使用
getanID
(也可以从“splitstackshape”中):

另外两列将是:

  • .id
    ,由
    getanID
    创建。此列与“PID”列组合时将创建唯一的ID
  • .time\u 1
    ,它是“叠加”步骤的结果,指示值来自哪个“提示”列(在本例中,在1和2之间循环表示“提示1”和“提示2”)

代码中读取
[,c(“PID”,“Cue”),with=FALSE]
的部分意味着只向我们显示这两列(因为这似乎就是您感兴趣的内容)。

您所说的优雅是什么意思?在紧凑性方面?在我的解决方案中,我必须为PID添加一个新列,再加上另一个列来标识列中的值是来自cue1还是来自CUE2(在上面的示例中未显示)。我认为已经有了一种更简洁、更简单的方法。请看我的答案。希望它能满足你的一些期望:)你说的优雅是什么意思?在紧凑性方面?在我的解决方案中,我必须为PID添加一个新列,再加上另一个列来标识列中的值是来自cue1还是来自CUE2(在上面的示例中未显示)。我认为已经有了一种更简洁、更简单的方法。请看我的答案。希望它能满足你的一些期望:)谢谢你的回答。这几乎是我想要的,也许我解释得很模糊,所以我试着纠正自己。更具体地说,行的确切顺序很重要。d1中新的长列(d1$trigger)应该以d[1,2]开始,然后是d[1,3],然后是d[2,2],d[2,3],d[3,2],d[4,2],d[4,3],d[5,2],d[5,3],d[6,2]和d[6,3]……因此在最后,我将分别对PID 1和PID 2使用所有触发器。在您的解决方案中,PID是交替的。如果我使用d3[order(d3$PID),],那么触发器的顺序将丢失。为什么保持准确的顺序如此重要?数据是相同的。你想做什么这么严格?我想比较我发送的触发器和我收到的触发器,以确保它被正确发送/解释。你不能也对“已发送”触发器进行排序,然后进行比较吗?如果您能提供一个完整的比较示例以及当前失败的地方,也许这将是最好的。然后,如果我使用上面的代码,也就是我在提问时编写的代码,会更容易。我可以转换df并创建一个向量,然后简单地比较这些值。我认为对于这种重塑过程有一个简洁的解决方案。谢谢你的回答。这几乎是我想要的,也许我解释得很模糊,所以我试着纠正自己。更具体地说,行的确切顺序很重要。d1中新的长列(d1$trigger)应该以d[1,2]开始,然后是d[1,3],然后是d[2,2],d[2,3],d[3,2],d[4,2],d[4,3],d[5,2],d[5,3],d[6,2]和d[6,3]……因此在最后,我将分别对PID 1和PID 2使用所有触发器。在您的解决方案中,PID是交替的。如果我使用d3[order(d3$PID),],那么触发器的顺序将丢失。为什么保持准确的顺序如此重要?数据是相同的。你想做什么这么严格?我想比较我发送的触发器和我收到的触发器,以确保它被正确发送/解释。你不能也对“已发送”触发器进行排序,然后进行比较吗?如果你能提供一个完整的例子来说明这个比较,以及它目前失败的地方,也许这将是最好的
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
# 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
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")