【问题标题】:Converting data from wide to long for two variables [duplicate]将两个变量的数据从宽转换为长[重复]
【发布时间】:2018-10-06 04:36:41
【问题描述】:

我有一个包含两个宽格式变量的数据集,我想将其转换为长格式。我从厨师那里看到了 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
...

【问题讨论】:

    标签: r melt


    【解决方案1】:

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

    不幸的是,两组列都以字母P 开头。简单地指定 patterns("PH", "P") 将不起作用,因为 P 将匹配 PH 列以及 P 列,导致 24 行而不是 12 行。稍微修改的正则表达式 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
    

    请注意,需要使用setDT(graph.dat)data.table(graph.dat)graph.dat 强制转换为data.table 对象。否则,reshape2::melt() 将被分派到无法识别 patterns() 的 data.frame 对象上。

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

    数据

    library(data.table)
    graph.dat <- fread(
    "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",
    data.table = FALSE)
    

    【讨论】:

    • 非常感谢,Uwe Block!我确实看到了您提到的问题和答案,但我认为它只有一个变量。现在,我看到您对我的问题的回答,我对它有了更好的理解。再次感谢!
    【解决方案2】:

    base 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")
                     )))
    

    【讨论】:

    • 感谢 r.user.05apr!我会试试你的解决方案
    【解决方案3】:

    使用基础 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"))
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-05-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-10-13
      • 2020-11-28
      • 2020-08-11
      相关资源
      最近更新 更多