使用do.call时丢失数据帧

时间:2011-11-01 22:09:11

标签: r dataframe

我正在尝试使用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)输出如下所示,其中sequence列不再是字符:

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获取实际数据框

谢谢。

3 个答案:

答案 0 :(得分:4)

有两个不同的问题会给你带来困难。

  • stringsAsFactors

你是正确的看stringsAsFactors,但是没有把它称为正确的地方。

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

options(stringsAsFactors=FALSE)

或者在用于创建data.table s:

的代码中
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.frame的列表,而不是单个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 <- list(a) < / p>

答案 1 :(得分:2)

使用Josh&#39;示例代码。我很确定发生的事情是这样的:

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)

什么都不做,因为只有一个参数。即没有任何东西可以附加到数据框,因此它只返回相同的数据帧。然后:

do.call("rbind", x)

这里发生的是使用列表rbind()中的所有参数调用x。数据框是列为元素的列表。因此,这将与:

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

所以你按行排列三个向量。因此,这成为你所拥有的转置,因为data.frames只存储不同类型的向量列,这必须成为一个字符矩阵。

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

答案 2 :(得分:1)

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

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