簡體   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