将数据从wide转换为long用于两个变量

时间:2017-07-04 00:15:58

标签: r melt

我有一个包含两个宽格式变量的数据集,我希望将其转换为long。我已经看过厨师为R做的例子,但他们只是一个变量。

我的数据集(graph.dat)如下所示:

 PH25   PH50    PH75    PH100   P25      P50    P75    P100      r_b    c
3.96    5.94    5.94    5.94    1,694   1,736   1,329   800     0.029   7
2.86    2.86    2.86    2.86    1,665   1,792   1,639   1,335   0.027   7
3.96    5.72    5.72    5.72    1,580   1,560   1,156   663     0.023   7

我想绘制PH(x轴)与P(y轴)。因此,对于PH25值,对应于P25的值(以及r_b和c的值);所以长格式将是:

PH       P      r_b         c
3.96    1,694   0.029       7
2.86    1,665   0.027       7
3.96    1,580   0.023       7
5.94    1,736   0.029       7
2.86    1,792   0.027       7
5.72    1,560   0.023       7
5.94    1,329   0.029       7
2.86    1,639   0.027       7
5.72    1,156   0.023       7
5.94    800     0.029       7
2.86    1,335   0.027       7
5.72    663     0.023       7

我试着“融化”它两次,但它不起作用。 这是我做的:

graph.dat1<- melt(graph.dat, id.vars=c("PH25","PH50","PH75",
                                        "PH100","r_b", "c"),
                             variable.name="P", 
                             value.name="Pval")

并且新数据集(graph.dat1)很好,因为我每个“P”只有三个值(总共给出12个观察值)。它看起来像这样:

    PH25    PH50    PH75    PH100   r_b     c    P     Pval
1   3.96    5.94    5.94    5.94    0.029   7   P25    1694
2   2.86    2.86    2.86    2.86    0.027   7   P25    1665
3   3.96    5.72    5.72    5.72    0.023   7   P25    1580
4   3.96    5.94    5.94    5.94    0.029   7   P50    1736
5   2.86    2.86    2.86    2.86    0.027   7   P50     1792
6   3.96    5.72    5.72    5.72    0.023   7   P50     1560
7   3.96    5.94    5.94    5.94    0.029   7   P75     1329
8   2.86    2.86    2.86    2.86    0.027   7   P75     1639
9   3.96    5.72    5.72    5.72    0.023   7   P75     1156
10  3.96    5.94    5.94    5.94    0.029   7   P100    800
11  2.86    2.86    2.86    2.86    0.027   7   P100    1335
12  3.96    5.72    5.72    5.72    0.023   7   P100    663

但当我做第二次“融化”时,它不起作用,我不知道如何解决它。这是我做的第二步:

graph.dat2<- melt (graph.dat1,id.vars=c("r_b", "c", "P", "Pval"),
                   variable.name="PdH",
                   value.name="PH")

然后我获得了4次观测数(因此,我得到48次观察而不是12次观察)。所以,我的新数据集(graph.dat2)看起来像:

    r_b     c   P     Pval  PdH      PH
1   0.029   7   P25   1694  PH25    3.96
2   0.027   7   P25   1665  PH25    2.86
3   0.023   7   P25   1580  PH25    3.96
4   0.029   7   P50   1736  PH25    3.96
5   0.027   7   P50   1792  PH25    2.86
6   0.023   7   P50   1560  PH25    3.96
7   0.029   7   P75   1329  PH25    3.96
8   0.027   7   P75   1639  PH25    2.86
9   0.023   7   P75   1156  PH25    3.96
10  0.029   7   P100   800  PH25    3.96
11  0.027   7   P100  1335  PH25    2.86
12  0.023   7   P100   663  PH25    3.96
13  0.029   7   P25   1694  PH50    5.94
14  0.027   7   P25   1665  PH50    2.86
15  0.023   7   P25   1580  PH50    5.72
...

3 个答案:

答案 0 :(得分:1)

data.table的最新版本允许melt multiple columns simultaneously

不幸的是,两组列都以字母P开头。简单地指定patterns("PH", "P")将不起作为P将匹配PH列以及P列,从而产生24行而不是12行。略微修改的正则表达式{ {1}}将起作用:

patterns("PH", "P\\d")
library(data.table)   # CRAN version 1.10.4 used
graph.dat1 <- melt(setDT(graph.dat), measure.vars = patterns("PH", "P\\d"), 
     value.name = c("PH", "P"))
# rename factor levels of variable
graph.dat1[, variable := forcats::lvls_revalue(variable, c("25", "50", "75", "100"))][]

请注意,您需要使用 r_b c variable PH P 1: 0.029 7 25 3.96 1,694 2: 0.027 7 25 2.86 1,665 3: 0.023 7 25 3.96 1,580 4: 0.029 7 50 5.94 1,736 5: 0.027 7 50 2.86 1,792 6: 0.023 7 50 5.72 1,560 7: 0.029 7 75 5.94 1,329 8: 0.027 7 75 2.86 1,639 9: 0.023 7 75 5.72 1,156 10: 0.029 7 100 5.94 800 11: 0.027 7 100 2.86 1,335 12: 0.023 7 100 5.72 663 graph.datdata.table强制转换为setDT(graph.dat)个对象。否则,将在无法识别data.table(graph.dat)的data.frame对象上调度reshape2::melt()

另请注意,类似问题的答案为here,但所需的patterns()则完全不同。

数据

patterns()

答案 1 :(得分:1)

基地R的另一种解决方案是:

df <- read.table(header=TRUE, text="PH25   PH50    PH75    PH100   P25          P50    P75    P100      r_b    c
3.96    5.94    5.94    5.94    1,694   1,736   1,329   800     0.029   7
2.86    2.86    2.86    2.86    1,665   1,792   1,639   1,335   0.027   7
3.96    5.72    5.72    5.72    1,580   1,560   1,156   663     0.023   7")

(want<-do.call(rbind,
               Map(
                 function(x,y) data.frame(PH=df[[x]],P=df[[y]],r_b=df$r_b,c=df$c),
                 c("PH25","PH50","PH75","PH100"),
                 c("P25","P50","P75","P100")
                 )))

答案 2 :(得分:0)

使用基数R reshape也不太困难:

reshape(df, direction="long", varying=list(paste0("PH", 1:4*25), paste0("P", 1:4*25)))
# note: paste0("PH", 1:4*25) is shortcut for c("PH25", "PH50", "PH75", "PH100")

..设置正确的名称(长格式为PH,而不是PH25

reshape(df, direction="long", varying=list(paste0("PH", 1:4*25), paste0("P", 1:4*25)),
    v.names=c("PH", "P"))