【问题标题】:losing dataframe when using do.call使用 do.call 时丢失数据帧
【发布时间】:2011-12-19 21:17:16
【问题描述】:

我正在尝试使用 rbind 合并多个数据帧。如果我直接调用 rbind 就没有问题:

> test <- rbind(x)
> is.data.frame(x)
[1] TRUE

但是,如果我使用do.call,我会遇到一个问题,即我的字符列被折叠并且数据框被转换为矩阵。

>test <- do.call("rbind", x)
> is.data.frame(test)
[1] FALSE

根据 ?rbind 文档,我尝试了add stringsAsFactors = FALSE,但行为没有改变。我的数据表如下所示:

ID  sequence    descriptor
1   aaacccttt   g12
2   actttgtgt   e34
3   tttgggctc   b12
4   ccgcgcgcg   c12
…   …       ...

rbind 输出看起来像这样,但do.call("rbind", x) 输出如下所示,其中序列列不再是字符:

ID  363 426 91
Sequence 98 353 100
descriptor  g12 b12 c12 

我想使用 do.call,因为我正在循环一组数据帧,以便使用下面的脚本合并它们。另一个有用的答案可能会提供有关如何在循环调用多个数据帧时合并多个数据帧的替代解决方案。

stringsAsFactors = FALSE
dfs <- as.list(ls(pattern="Data_"))
for (i in 1:length(dfs)) {
  x <- get(as.character(dfs[i]))
  AllData <- do.call("rbind", x) 
  }

dfs 是我工作环境中的数据帧列表,我使用get 获取实际数据帧

谢谢。

【问题讨论】:

    标签: r dataframe


    【解决方案1】:

    有两个不同的问题会导致您遇到困难。

    • stringsAsFactors

    您查看stringsAsFactors 是对的,但只是没有在正确的地方调用它。

    你有两个选择。您可以在options 中设置它,如下所示:

    options(stringsAsFactors=FALSE)
    

    或者在用于创建data.tables 的代码中:

    a <- read.table(textConnection("ID  sequence    descriptor
    1   aaacccttt   g12
    2   actttgtgt   e34
    3   tttgggctc   b12
    4   ccgcgcgcg   c12"),
    header=T, stringsAsFactors=FALSE)
    
    • args= do.call() 的参数

    您希望为此使用do.call() 也是正确的。但是,正如@Sacha 指出的那样,dfs 需要是 data.frames 的列表,而不是单个 data.frame(它本身就是向量列表)。

    # Create list of two data.frames
    b <- a
    dfs <- list(a, b)
    
    # Or, if you start with a list of their names
    dfs <- list("a", "b")
    dfs <- lapply(dfs, get)
    
    # Check that this works
    do.call("rbind", dfs)
    #   ID  sequence descriptor
    # 1  1 aaacccttt        g12
    # 2  2 actttgtgt        e34
    # 3  3 tttgggctc        b12
    # 4  4 ccgcgcgcg        c12
    # 5  1 aaacccttt        g12
    # 6  2 actttgtgt        e34
    # 7  3 tttgggctc        b12
    # 8  4 ccgcgcgcg        c12
    

    即使您只有一个 data.frame,这也应该适用于您,只要它包含在 (length-1) list 中,就像这样:dfs &lt;- list(a)

    【讨论】:

      【解决方案2】:

      我认为使用Reduce 可以在没有循环的情况下完成您所寻求的。它是一个高阶函数,它将一个函数依次应用于列表中的两个元素。

      dfs <- as.list(ls(pattern="Data_"))
      Reduce('rbind', dfs)
      

      【讨论】:

      • 谢谢 Ramnath,但是当我尝试这种方法时,我不返回数据集,而是返回字符矩阵。我不知道 Reduce,所以我一定会研究它。
      【解决方案3】:

      使用 Josh 的示例代码。我很确定正在发生的事情是这样的:

      Data:
          x <- read.table(textConnection("ID  sequence    descriptor
          1   aaacccttt   g12
          2   actttgtgt   e34
          3   tttgggctc   b12
          4   ccgcgcgcg   c12"),
          header=T, stringsAsFactors=FALSE)
      

      首先是这个:

      rbind(x)
      

      什么都不做,因为只有一个参数。 IE。没有要附加到数据帧的内容,因此它只返回相同的数据帧。那么:

      do.call("rbind", x)
      

      这里发生的情况是rbind() 使用列表x 中的所有参数调用。数据框是一个以列为元素的列表。因此,这将与以下内容相同:

      rbind(x$ID,x$sequence,x$descriptor)
      

      所以你将三个向量按行放在一起。因此,这成为您所拥有的转置,并且由于 data.frames 仅按列存储不同类型的向量,因此它必须成为字符矩阵。

      我认为如果x 是一个数据框列表,它可以正常工作。它本身不应该是一个数据框。

      【讨论】:

      • 谢谢你,Sacha,我认为你已经完美地描述了发生的事情
      猜你喜欢
      • 2013-10-21
      • 2015-04-24
      • 2023-04-10
      • 1970-01-01
      • 2020-08-21
      • 2014-03-13
      • 2013-01-11
      • 2019-01-11
      • 2018-08-19
      相关资源
      最近更新 更多