【问题标题】:Reshaping data frame in R [duplicate]在R中重塑数据框[重复]
【发布时间】:2010-12-04 17:53:42
【问题描述】:

我在重塑大型数据框时遇到了困难。而且我过去相对幸运地避免了重塑问题,这也意味着我在这方面很糟糕。

我当前的数据框看起来像这样:

unique_id    seq   response    detailed.name    treatment 
a            N1     123.23     descr. of N1     T1
a            N2     231.12     descr. of N2     T1
a            N3     231.23     descr. of N3     T1
...
b            N1     343.23     descr. of N1     T2
b            N2     281.13     descr. of N2     T2
b            N3     901.23     descr. of N3     T2
...

我想:

seq    detailed.name   T1           T2
N1     descr. of N1    123.23       343.23
N2     descr. of N2    231.12       281.13
N3     descr. of N3    231.23       901.23

我查看了 reshape 包,但我不确定如何将处理因子转换为单独的列名。

谢谢!

编辑:我尝试在我的本地机器(4GB 双核 iMac 3.06Ghz)上运行它,但它一直失败:

> d.tmp.2 <- cast(d.tmp, `SEQ_ID` + `GENE_INFO` ~ treatments)
Aggregation requires fun.aggregate: length used as default
R(5751) malloc: *** mmap(size=647168) failed (error code=12)
*** error: can't allocate region
*** set a breakpoint in malloc_error_break to debug

如果有机会,我会尝试在我们的一台更大的机器上运行它。

【问题讨论】:

  • 哦,如果您遇到内存问题,您可能需要权衡空间/速度。由于您的 df 似乎是可预测的排序和分组,没有长距离依赖关系,C 风格的嵌套 for 循环可能是有序的。您必须在创建新 df 时对其进行扩展,但您不会像melt-cast 那样复制和围绕巨大的向量进行抛锚......
  • 哈兰所说的。最后合并的子集可能更容易/更清洁编程。或者,也许你只是想让我们说它“没问题”,你真的“需要”8GB 的​​内存,你已经考虑了一段时间来运行 64 位 R ;)
  • R 中的熔化和铸造是可有效用于重塑数据的函数。用于执行此操作的函数称为 melt() 和 cast()。已在datasciencemadesimple.com/melting-casting-r 中举例说明

标签: r dataframe reshape


【解决方案1】:

另一种选择是使用tidyr中的spread

library(tidyr) 
Wide1 <- spread(x[-1], treatment, response)
Wide1
#  seq detailed.name     T1     T2
#1  N1           dN1 123.23 343.23
#2  N2           dN2 231.12 281.13
#3  N3           dN3 231.23 901.23

相反的动作由gather执行

gather(Wide1, detailed.name, response, T1:T2)
#  seq detailed.name detailed.name response
#1  N1           dN1            T1   123.23
#2  N2           dN2            T1   231.12
#3  N3           dN3            T1   231.23
#4  N1           dN1            T2   343.23
#5  N2           dN2            T2   281.13
#6  N3           dN3            T2   901.23

另外,还有dcast.data.table来自data.table

library(data.table)
dcast.data.table(setDT(x), seq + detailed.name~treatment,
                                          value.var='response')
#   seq detailed.name     T1     T2
#1:  N1           dN1 123.23 343.23
#2:  N2           dN2 231.12 281.13
#3:  N3           dN3 231.23 901.23

数据

x <- structure(list(unique_id = structure(c(1L, 1L, 1L, 2L, 2L, 2L
), .Label = c("a", "b"), class = "factor"), seq = structure(c(1L, 
2L, 3L, 1L, 2L, 3L), .Label = c("N1", "N2", "N3"), class = "factor"), 
response = c(123.23, 231.12, 231.23, 343.23, 281.13, 901.23
), detailed.name = structure(c(1L, 2L, 3L, 1L, 2L, 3L), .Label = c("dN1", 
"dN2", "dN3"), class = "factor"), treatment = structure(c(1L, 
1L, 1L, 2L, 2L, 2L), .Label = c("T1", "T2"), class = "factor")), .Names =
c("unique_id", "seq", "response", "detailed.name", "treatment"), class = 
"data.frame", row.names = c(NA, -6L))

【讨论】:

    【解决方案2】:

    如果您想使用reshape2 获得相同的结果,这是对reshape 包的更快且更节省内存的重写,那么以下将起作用。

    主要的变化是当你想castdata.frame 作为输出时使用dcast 函数。这替换了reshapecast 函数

    library(reshape2)
    
    x = read.table(text = "unique_id seq   response  detailed.name treatment
                               a      N1    123.23         dN1        T1
                               a      N2    231.12         dN2        T1
                               a      N3    231.23         dN3        T1
                               b      N1    343.23         dN1        T2
                               b      N2    281.13         dN2        T2
                               b      N3    901.23         dN3        T2", 
    sep = "", header = TRUE)
    
    x
    
    y <- dcast(x, seq + detailed.name ~ treatment, value.var = "response")
    y
    #   seq detailed.name     T1     T2
    # 1  N1           dN1 123.23 343.23
    # 2  N2           dN2 231.12 281.13
    # 3  N3           dN3 231.23 901.23
    
    # EDIT to show how to return to the original data set:
    
    melt(y, id.vars=c('seq', 'detailed.name'), variable.name='T', value.name='response')
    
    #   seq detailed.name  T response
    # 1  N1           dN1 T1   123.23
    # 2  N2           dN2 T1   231.12
    # 3  N3           dN3 T1   231.23
    # 4  N1           dN1 T2   343.23
    # 5  N2           dN2 T2   281.13
    # 6  N3           dN3 T2   901.23
    

    【讨论】:

    • reshape2reshape 的重写,以更快和更节省内存。它不向后兼容reshape,因此是新包,而不是旧包的新版本。
    • @Mark Miller:你使用这个工具的最大数据框是什么?
    【解决方案3】:

    以 Harlan 的回答为基础 - 如果数据已经是长格式,并且在 cast 调用中指定了保存值的列,则可以避免重熔步骤。

    > x <- read.table(textConnection("  unique_id seq response detailed.name treatment
    + 1         a  N1   123.23           dN1        T1
    + 2         a  N2   231.12           dN2        T1
    + 3         a  N3   231.23           dN3        T1
    + 4         b  N1   343.23           dN1        T2
    + 5         b  N2   281.13           dN2        T2
    + 6         b  N3   901.23           dN3        T2"))
    > 
    > cast(x, seq + detailed.name ~ treatment, value = "response")
      seq detailed.name     T1     T2
    1  N1           dN1 123.23 343.23
    2  N2           dN2 231.12 281.13
    3  N3           dN3 231.23 901.23
    

    【讨论】:

      【解决方案4】:

      您还可以使用stats 包中的reshape 函数。我没有你的示例数据集,但它看起来像这样:

      reshape(x, idvar=c("seq","detailed.name"), timevar="treatment", direction="wide")
      

      【讨论】:

        【解决方案5】:

        reshape 对我来说也总是很棘手,但它似乎总是通过一些试验和错误来工作。这是我最终发现的:

        > x
          unique_id seq response detailed.name treatment
        1         a  N1   123.23           dN1        T1
        2         a  N2   231.12           dN2        T1
        3         a  N3   231.23           dN3        T1
        4         b  N1   343.23           dN1        T2
        5         b  N2   281.13           dN2        T2
        6         b  N3   901.23           dN3        T2
        
        > x2 <- melt(x, c("seq", "detailed.name", "treatment"), "response")
        > x2
          seq detailed.name treatment variable  value
        1  N1           dN1        T1 response 123.23
        2  N2           dN2        T1 response 231.12
        3  N3           dN3        T1 response 231.23
        4  N1           dN1        T2 response 343.23
        5  N2           dN2        T2 response 281.13
        6  N3           dN3        T2 response 901.23
        
        > cast(x2, seq + detailed.name ~ treatment)
          seq detailed.name     T1     T2
        1  N1           dN1 123.23 343.23
        2  N2           dN2 231.12 281.13
        3  N3           dN3 231.23 901.23
        

        您的原始数据已经是长格式,但不是 melt/cast 使用的长格式。所以我重新融化了它。第二个参数(id.vars)是不融化的东西的列表。第三个参数 (measure.vars) 是变化的事物的列表。

        然后,演员使用一个公式。波浪号左边是保持原样的东西,波浪号右边是用于调节值列的列。

        或多或少...!

        【讨论】:

        • 伙计,你很快,哈伦。文斯,我总是尽量记住,cast() 中“+”右侧的任何内容最终都会作为最终数据框中包含值的列。
        猜你喜欢
        • 2014-11-09
        • 1970-01-01
        • 1970-01-01
        • 2017-02-11
        • 1970-01-01
        相关资源
        最近更新 更多