【问题标题】:Casting and Melting with reshape in R在 R 中使用 reshape 进行铸造和熔化
【发布时间】:2018-07-24 22:51:33
【问题描述】:

例如,假设我有以下数据框:

datas=data.frame(Variables=c("Power","Happiness","Power","Happiness"),
Country=c("France", "France", "UK", "UK"), y2000=c(1213,1872,1726,2234), y2001=c(1234,2345,6433,9082))

导致以下输出:

  Variables Country  2000  2001
1 Power     France   1213  1234
2 Happiness France   1872  2345
3 Power     UK       1726  6433
4 Happiness UK       2234  9082

我想按如下方式重塑这个数据框:

  Year      Country  Power Happiness
1 2000      France    1213      1872  
2 2001      France    1234      2345
3 2000      UK        1726      2234
4 2001      UK        6433      9082

我一开始是:

q2=cast(datas, Country~Variables, value="2000")

但随后出现以下错误:

Aggregation requires fun.aggregate: length used as default
Error in `[.data.frame`(sort_df(data, variables), , c(variables, "value"),  : 
  undefined columns selected

有什么建议吗? 另外:我的数据框真的很大(417120 x 62)对解决方案有影响吗?

【问题讨论】:

    标签: r reshape


    【解决方案1】:

    也许您对tidyverse 替代方案感兴趣

    library(tidyverse)
    df %>%
        gather(Year, val, -Variables, -Country) %>%
        spread(Variables, val)
    #  Country Year Happiness Power
    #1  France 2000      1872  1213
    #2  France 2001      2345  1234
    #3      UK 2000      2234  1726
    #4      UK 2001      9082  6433
    

    或者使用reshape2::meltreshape2::dcast

    reshape2::dcast(
        reshape2::melt(df, id.vars = c("Country", "Variables"), variable.name = "Year"),
        Country + Year ~ Variables)
    #        Country Year Happiness Power
    #1  France 2000      1872  1213
    #2  France 2001      2345  1234
    #3      UK 2000      2234  1726
    #4      UK 2001      9082  6433
    

    或者(同样)使用data.table::meltdata.table::dcast

    data.table::dcast(
        data.table::melt(df, id.vars = c("Country", "Variables"), variable.name = "Year"), 
        Country + Year ~ Variables)
    #  Country Year Happiness Power
    #1  France 2000      1872  1213
    #2  France 2001      2345  1234
    #3      UK 2000      2234  1726
    #4      UK 2001      9082  6433
    

    就性能/运行时间而言,我认为data.tabletidyr 解决方案是最有效的。您可以通过对一些较大的样本数据运行microbenchmark 来检查。


    样本数据

    df <-read.table(text =
        "  Variables Country  2000  2001
    1 Power     France   1213  1234
    2 Happiness France   1872  2345
    3 Power     UK       1726  6433
    4 Happiness UK       2234  9082", header = T)
    colnames(df)[3:4] <- c("2000", "2001")
    

    基准分析

    以下是对四种方法的microbenchmark 分析结果,基于(稍大)的78x22 样本数据集。

    set.seed(2017)
    df <- data.frame(
        Variables = rep(c("Power", "Happiness", "something_else"), 26),
        Country = rep(LETTERS[1:26], each = 3),
        matrix(sample(10000, 20 * 26 * 3), nrow = 26 * 3))
    colnames(df)[3:ncol(df)] <- 2000:2019
    
    library(microbenchmark)
    library(tidyr)
    
    res <- microbenchmark(
        reshape2 = {
            reshape2::dcast(
                reshape2::melt(df, id.vars = c("Country", "Variables"), variable.name = "Year"),
                Country + Year ~ Variables)
        },
        tidyr = {
            df %>%
                gather(Year, val, -Variables, -Country) %>%
                spread(Variables, val)
        },
        datatable = {
            data.table::dcast(
                data.table::melt(df, id.vars = c("Country", "Variables"), variable.name = "Year"),
                Country + Year ~ Variables)
        },
        reshape = {
            reshape::cast(reshape::melt(df), Country + variable ~ Variables)
        }
    )
    res
    #Unit: milliseconds
    #      expr       min        lq      mean    median        uq       max neval
    #  reshape2  3.088740  3.449686  4.313044  3.919372  5.112560  7.856902   100
    #     tidyr  4.482361  4.982017  6.215872  5.771133  6.931964 28.293377   100
    # datatable  3.179035  3.511542  4.861192  4.040188  5.123103 46.010810   100
    #   reshape 27.371094 30.226222 32.425667 32.504644 34.118499 41.286803   100
    
    library(ggplot2)
    autoplot(res)
    

    【讨论】:

    • library(tidyr) 就足够了。
    • 非常感谢您的广泛回答。我想按照建议使用 tidyverse 解决方案,但我在阅读语法时遇到了一些麻烦。如果我应用 tidyverse 解决方案,我会收到错误:Error in is_character(x) : object 'Variables' not found。难道是我首先必须定义哪些是变量? Variables &lt;- df[,2] 之类的东西?
    • @TomKisters Variables 是样本数据的列名之一。在gather(Year, val, -Variables, -Country) 中,我们将数据从宽转长,存储除VariablesCountry 之外的所有列的列名Yearval 中的值。
    • 不客气@TomKisters,绝对不需要道歉,我们都去过那里;-)
    • @TomKisters PS。我很好奇,并添加了快速基准分析;似乎data.tablereshape2 是两种最快的方法;但是,样本数据仍然很小,因此对于较大的数据集,结果可能会发生变化...
    【解决方案2】:

    如上所述,我强烈建议使用tidyr 而不是reshape,或者至少使用reshape2 而不是reshape,因为它解决了reshape 的许多性能问题。

    reshape本身,你必须先融化datas

    > cast(melt(datas), Country + variable ~ Variables)
    Using Variables, Country as id variables
      Country variable Happiness Power
    1  France    y2000      1872  1213
    2  France    y2001      2345  1234
    3      UK    y2000      2234  1726
    4      UK    y2001      9082  6433
    

    然后根据需要重命名和转换列。

    reshape2 中的代码是相同的,但您可以使用dcast 而不是casttidyr,正如上面@Maurits Evers 的解决方案是一个更好的解决方案,大多数开发已经从reshape2 转移到tidyverse

    【讨论】:

      猜你喜欢
      • 2019-02-08
      • 2016-12-18
      • 2017-06-24
      • 1970-01-01
      • 1970-01-01
      • 2014-07-12
      • 1970-01-01
      • 1970-01-01
      • 2011-09-17
      相关资源
      最近更新 更多