【问题标题】:More elegant way of transforming data frames from wide to long data fromat by using reshape() or melt()使用 reshape() 或 melt() 将数据帧从宽数据格式转换为长数据格式的更优雅方式
【发布时间】:2014-12-16 13:04:37
【问题描述】:

我正在寻找一种更优雅的方式来通过使用 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
...

不幸的是,互联网上关于 reshape 的大多数示例都讨论了以下(在我的情况下是非首选)示例:

trigger
1
2
3
1
2
3
...

但我需要前一个。

提前感谢您的建议。

【问题讨论】:

  • 优雅是什么意思?在紧凑性方面?不要认为任何变体都会比你所做的要短得多。
  • 在我的解决方案中,我必须为 PID 添加一个新列,以及另一个用于识别列中的值是来自 cue1 还是 2 的列(上例中未显示)。我认为已经有一种更紧凑、更简单的方法来做到这一点。
  • 看我的回答。希望它能满足你的一些期望:)

标签: r reshape


【解决方案1】:

最简单的方法是使用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

【讨论】:

  • 感谢您的回答。这几乎是我想要的,也许我解释得含糊不清,所以我试着纠正自己。更具体地说,行的确切顺序很重要。 d1 (d1$trigger) 中的新长列应以 d[1,2] 然后 d[1,3] 开头,然后是 d[2,2]、d[2,3]、d[3,2 ]、d[3,3]、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 并创建一个向量并简单地比较这些值。我认为这种重塑过程有一个简洁的解决方案。
【解决方案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,这是“堆叠”步骤的结果,用于指示值来自哪个“提示”列(在这种情况下,在 1 和 2 之间循环表示“提示 1”和“提示 2”)。

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

【讨论】:

【解决方案3】:

如果您只是在寻找使用融化的单线,以下是一种方法(保留所需的顺序):

# 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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-10-22
    • 1970-01-01
    • 2021-10-08
    相关资源
    最近更新 更多