【问题标题】:rbind text files with different length of rowsrbind 具有不同行长的文本文件
【发布时间】:2015-04-26 14:56:54
【问题描述】:

我正在尝试使用 dif.length of rows rbind 两个 txt 文件,例如:

我使用这个代码:

a<-matrix(1:12,4,3)
b<-matrix(21:41,7,3)

setwd("test/")
write.table(a, file="a.txt",quote=FALSE,  row.names=FALSE,col.names=FALSE)
write.table(b, file="b.txt",quote=FALSE, row.names=FALSE, col.names=FALSE)
file_list <- list.files()
g<- do.call(rbind,lapply(file_list,FUN=function(files){scan(files,what = character())}))

我收到这条警告信息:

"在 (function (..., deparse.level = 1) : 结果的列数不是向量长度的倍数(arg 1)"

我希望 g 看起来像这样:

##       [,1] [,2] [,3]
##  [1,]    1    5    9
##  [2,]    2    6   10
##  [3,]    3    7   11
##  [4,]    4    8   12
##  [5,]   21   28   35
##  [6,]   22   29   36
##  [7,]   23   30   37
##  [8,]   24   31   38
##  [9,]   25   32   39
## [10,]   26   33   40
## [11,]   27   34   41

我是新手,有什么解决方案吗? 非常感谢,

【问题讨论】:

  • 您是否应该探索为什么会出现此错误而不是想要一个蛮力解决方案,尤其是因为您是 r 新手?
  • 我已经在探索解决方案,但我没有解决。
  • 对于一个新手来说,你的第一篇文章比我当时的第一篇文章要好得多。我不确定你的意思,但似乎 rbind(a,b) 产生了上述输出。
  • rbind.fill 来自 plyr 包可能有效。
  • 我找到了这个链接psychwire.wordpress.com/2011/06/03/…,但我仍然有同样的问题。谢谢你的评论rawr

标签: r


【解决方案1】:

除非您另有说明,否则scan() 会将整个文件作为单个原子向量读取。您可以将列表传递给what 参数,但使用读取结构化数据的函数会更容易、更安全。此外,您不想使用what = character(),因为您正在读取数值。

基础 R 中的read.table() 和包“data.table”中的fread() 可以很容易地做到这一点。

files <- c("a.txt", "b.txt")

## read.table()
data.matrix(do.call(rbind, lapply(files, read.table)), rownames.force = FALSE)

## fread()
library(data.table)
data.matrix(rbindlist(lapply(files, fread)))

这两个都返回矩阵

#       V1 V2 V3
#  [1,]  1  5  9
#  [2,]  2  6 10
#  [3,]  3  7 11
#  [4,]  4  8 12
#  [5,] 21 28 35
#  [6,] 22 29 36
#  [7,] 23 30 37
#  [8,] 24 31 38
#  [9,] 25 32 39
# [10,] 26 33 40
# [11,] 27 34 41

如果你真的想使用scan(),你可以将一个列表传递给what 参数来告诉它列数。

## get number of columns
nc <- max(unlist(lapply(files, count.fields)))
## read as a list, then bind together
do.call(rbind, lapply(files, function(x) {
    do.call(cbind, scan(x, what = as.list(double(nc)), quiet = TRUE))
}))
#       [,1] [,2] [,3]
#  [1,]    1    5    9
#  [2,]    2    6   10 
#  [3,]    3    7   11
#  [4,]    4    8   12
#  [5,]   21   28   35
#  [6,]   22   29   36
#  [7,]   23   30   37
#  [8,]   24   31   38
#  [9,]   25   32   39
# [10,]   26   33   40
# [11,]   27   34   41

但这只是count.fields(),然后是scan(),这基本上是read.table() 一步完成的。另外,如果数据中存在缺失值,这可能会有风险。

【讨论】:

    【解决方案2】:

    不过,我不喜欢扫描,但我确信它在某些情况下可以达到目的。

    因此,我建议使用 read.csv 和 write.csv:

    a<-matrix(1:12,4,3)
    b<-matrix(21:41,7,3)
    
    setwd("test/")
    write.csv(a, file="a.txt",row.names=FALSE,col.names=FALSE)
    write.csv(b, file="b.txt", row.names=FALSE, col.names=FALSE)
    file_list <- list.files()
    g <- do.call(rbind,lapply(file_list,FUN=function(files){read.csv(files)}))
    

    如果你看看?scan。您可能会发现为什么会出现错误。我的理解是它是在一行中读取表格:

     > scan('a.txt',what=character())
    ## Read 6 items
    ## [1] "V1"             ",\"V2\",\"V3\"" "1,5,9"          "2,6,10"        
    ## [5] "3,7,11"         "4,8,12"        
     > scan('b.txt',what=character())
    ## Read 9 items
    ## [1] "V1"             ",\"V2\",\"V3\"" "21,28,35"       "22,29,36"      
    ## [5] "23,30,37"       "24,31,38"       "25,32,39"       "26,33,40"      
    ## [9] "27,34,41"      
    

    【讨论】:

    • 感谢 DJJ 的尝试。这给出了同样的警告。关于扫描,你是对的。它在一行中读取表格。如果我有一个矩阵,我会用:a1
    • 抱歉代码中的一些错字。现在它应该工作得更好了。
    猜你喜欢
    • 1970-01-01
    • 2014-06-26
    • 2011-02-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多