0

我对 R 很陌生,但似乎这是一个我无法找到答案的特定问题。

我的程序读入一些数据,然后根据我传递的列号向量将该数据的某些列绑定到几个数据帧之一,所以是这样的:

filename <- c("vector", "full", "of", "filenames")
colVal <- (32)    
InMat <- data.frame()
for (i in 1:length(filename)){
  file <- read.table(filename[i], header=TRUE, fill=TRUE, stringsAsFactors=FALSE)
  InMat <- rbind(InMat, file[c(2:dim(file)[1], colVal)])
  #...other matricies...
}

我的问题在于只有一个所需列的情况,即 colVal 采用一个值。在这种情况下,我发现 InMat 基本上是从我所需要的转换而来的。更糟糕的是,当我读取多个文件时,它会绑定转置的所需列,因此我得到的行数等于我正在读取的文件数,列数与每个文件的每个所需列中的行数一样多。

似乎如果有 2 个所需的列(即 colVal 采用两个或多个值),那么它会按我的预期行事(即,一列被读取并作为一列存储在 InMat 中,每个附加文件的列存储在下面)。

我的问题是为什么 rbind 在只传递一个所需的列值时会有不同的行为,并且是否有一种简单的方法(读取;不添加一些笨拙的 if 或 for 循环来检查)来避免这种情况?

谢谢!

4

2 回答 2

1

简短回答:(数据帧上[.data.frame[运算符)默认情况下将输出转换为可能的最低维度(通过参数drop=TRUE)。如果你只拉一列,那么它会转换为一个向量,然后它会创建一个矩阵,将其他向量通过rbind转换为一个矩阵。当你提取两列或更多列时,你得到一个数据框,所以输出的rbind是一个数据框。

快速解决方法是更改​​此行:

InMat <- rbind(InMat, file[c(2:dim(file)[1], colVal)]) #old line
InMat <- rbind(InMat, file[c(2:dim(file)[1], colVal),drop=FALSE]) #new line

一种更像 R 的编码方式是使用lapply并调用rbind一次。因为 R 是按副本分配的,所以通过重复连接/添加来增长对象是非常低效的(参见R Inferno的第二个圆圈)。

filename <- c("vector", "full", "of", "filenames")
colVal <- (32)    
dfm <- lapply(filename, read.table
  , header=TRUE, fill=TRUE, stringsAsFactors=FALSE)
dfm <- lapply(dfm,`[`,colVal)
dfm <- do.call(rbind,dfm)

如果您事先知道要提取的列的位置,则可以使用colClasses参数 ofread.table并跳过阅读整个表格:

filename <- c("vector", "full", "of", "filenames")
colVal <- 32
cc <- rep.int("NULL",40) #where 40 is # of columns in table
cc[colVal] <- NA 
dfm <- lapply(filename, read.table
  , header=TRUE, fill=TRUE, colClasses=cc, stringsAsFactors=FALSE)
dfm <- do.call(rbind,dfm)
于 2013-03-14T18:23:25.747 回答
0

当你只取一列时,它就变成了一个向量。如果您只是将所有值附加到向量而不是矩阵中会更好

InVec <- c()
for (i in 1:length(filename)){
  file <- read.table(filename[i], header=TRUE, fill=TRUE, stringsAsFactors=FALSE)
  InVec <- c(InVec, file[-1, colVal)])
  #...other matricies...
}

使用 c() 也将比 rbind 快得多

于 2013-03-14T15:20:09.880 回答