繁体   English   中英

如何使用R“ readLines”命令从大文件中读取选定的行并将其写入数据帧?

[英]How can I read selected rows from a large file using the R “readLines” command and write them to a data frame?

我从事数据清理。 我有一个函数,可以识别大型输入文件中的不良行(给定我的RAM大小,太大而无法读取),并将不良行的行号作为向量badRows 此功能似乎起作用。

我现在试图将不良行仅读取到数据帧中,但迄今为止未成功。

我当前的方法是在打开的文件连接上使用read.table ,使用行数向量在要读取的每一行之间跳过。 对于连续的坏行,此数字为零。

我将skipVec计算为:

(badRowNumbers - c(0, badRowNumbers[1:(length(badRowNumbers-1]))-1

但是目前,我只是给我的函数一个全零的skipVec向量。

如果我的逻辑正确,则应返回所有行。 它不是。 相反,我得到一个错误:

“ read.table(con,skip = pass,nrow = 1,header = TRUE,sep =“”)中的错误:输入中无可用行”

我当前的功能大致是基于Miron Kursa(“ mbq”)的功能,我在这里找到了该功能

我的问题与那个问题有些重复,但是我认为他的功能有效,所以我以某种方式打破了它。 我仍在尝试了解打开文件和打开文件连接之间的区别,并且我怀疑问题出在某处或使用lapply

我在带有3gig ram的老旧Windows XP SP3机器上在RStudio 0.97.551下运行R 3.0.1。 我知道石器时代。

这是产生上述错误消息的代码:

# Make a small small test data frame, write it to a file, and read it back in 
# a row at a time.
testThis.DF <- data.frame(nnn=c(2,3,5), fff=c("aa", "bb", "cc"))  
testThis.DF 

# This function will work only if the number of bad rows is not too big for memory
write.table(testThis.DF, "testThis.DF")
con<-file("testThis.DF")
open(con)
skipVec <- c(0,0,0)
badRows.DF  <- lapply(skipVec, FUN=function(pass){
  read.table(con, skip=pass, nrow=1, header=TRUE, sep="") })
close(con)

该错误发生在关闭命令之前。 如果我从lapply和函数中抽出了readLines命令,然后将其单独粘贴,则仍然会遇到相同的错误。

如果不是通过lapply运行read.table而是手动运行前几个迭代,那么您会看到发生了什么:

> read.table(con, skip=0, nrow=1, header=TRUE, sep="")
  nnn fff
1   2  aa
> read.table(con, skip=0, nrow=1, header=TRUE, sep="")
  X2 X3 bb
1  3  5 cc

因为header = TRUE ,所以每次迭代读取的不是一行,而是两次,因此最终您的行数比您想像的快,在第三次迭代中:

> read.table(con, skip=0, nrow=1, header=TRUE, sep="")
Error in read.table(con, skip = 0, nrow = 1, header = TRUE, sep = "") : 
  no lines available in input

现在,这可能仍然不是解决问题的非常有效的方法,但是,这是解决当前代码的方法:

write.table(testThis.DF, "testThis.DF")
con <- file("testThis.DF")
open(con)
header <- scan(con, what = character(), nlines = 1, quiet = TRUE)
skipVec <- c(0,1,0)
badRows <- lapply(skipVec, function(pass){
  line <- read.table(con, nrow = 1, header = FALSE, sep = "",
                     row.names = 1)
  if (pass) NULL else line
  })
badRows.DF <- setNames(do.call(rbind, badRows), header)
close(con)

有关提高速度的一些线索:

  1. 使用scan而不是read.table 将数据作为character读取,并且仅在最后将数据放入字符矩阵或data.frame之后,将type.convert应用于每一列。
  2. 相反,遍历的skipVec ,遍历其rle如果要短得多。 这样您就可以一次读取或跳过几行。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM