在R中将大文件划分为小文件

在R中将大文件划分为小文件,r,loops,bigdata,chunks,R,Loops,Bigdata,Chunks,我需要将一个大文件(14GB)分解成更小的文件。这个文件的格式是txt,标签是“;”,我知道它有70列(字符串,双精度)。我想读一百万,并保存在不同的文件,文件1,文件2。。。菲伦 在@MKR的帮助下 但过程非常缓慢,我尝试使用fread,但不可能 如何优化此代码 新代码 chunkSize <- 10000 conex <- file(description = db, open = "r") data <- read.table(conex, nrows = chunkSi

我需要将一个大文件(14GB)分解成更小的文件。这个文件的格式是txt,标签是“;”,我知道它有70列(字符串,双精度)。我想读一百万,并保存在不同的文件,文件1,文件2。。。菲伦

在@MKR的帮助下

但过程非常缓慢,我尝试使用fread,但不可能

如何优化此代码

新代码

chunkSize <- 10000
conex <- file(description = db, open = "r")
data <- read.table(conex, nrows = chunkSize, header=T, fill=TRUE, sep =";")

index <- 0
counter <- 0
total <- 0
chunkSize <- 500000 
conex <- file(description=db,open="r")   
dataChunk <- read.table(conex, nrows=chunkSize, header=T, fill=TRUE,sep=";")

repeat {
dataChunk <- read.table(conex, nrows=chunkSize, header=FALSE, fill = TRUE, sep=";", col.names=db_colnames)
total <- total + sum(dataChunk$total)
counter <- counter + nrow(dataChunk)
write.table(dataChunk, file = paste0("MY_FILE_new",index),sep=";", row.names = FALSE)

  if (nrow(dataChunk) != chunkSize){
    print('linesok')
    break}
    index <- index + 1
  print(paste('lines', index * chunkSize))
}

chunkSize实现解决方案的方法完全正确

让我们在OP尝试行的循环中转换上述逻辑:

index <- 0
counter <- 0
total <- 0
chunks <- 500000

repeat{
  dataChunk <- read.table(con, nrows=chunks, header=FALSE, fill = TRUE,                 
                          sep=";", col.names=db_colnames)

  # do processing on dataChunk (i.e adding header, converting data type) 

  # Create a new file name and write to it. You can have your own logic for file names 
  write.table(dataChunk, file = paste0("file",index))

  #check if file end has been reached and break from repeat
  if(nrow(dataChunk) < chunks){
    break
  }

  #increment the index to read next chunk
  index = index+1

}

注意:以上代码只是帮助OP的部分代码片段的伪代码。它不会自行运行并产生结果。

不是基于R的答案,但在这种情况下,我建议使用GNU的
拆分
使用基于shell的解决方案。这应该比R解决方案快得多。

要将文件拆分为块,每个块有
10^6
行,您需要执行以下操作:

split -l 1000000 my_file.txt 

有关
split
的详细信息,请参阅例如..

@RYoda
read。table
的参数为
skip=
,其中可以指定要跳过的行数,但在这种情况下不需要,因为文件在循环开始之前只打开了一次。因此,
read.table
将自动从下一行开始。如果文件被关闭并打开,或者
文件名
被作为
读取.表格
的参数提供,则必须使用
跳过
。感谢您的帮助@MKR,我已经更改了代码,它工作了,但我想优化它。@JoyceMaia很高兴它帮助了您。您可以接受这个答案,这样对未来的用户来说就更容易了。我想建议您使用
data.table::fread
,但对于该函数,您必须维护
skip
。因此,我想不要把你搞糊涂,让你先找到一个解决方案。@JoyceMaia抱歉。刚才看到您对问题的更新。您已经考虑过使用
fread
。如果你愿意,我可以帮你用
fread
可以更快地多次读取文件。更改为fread时会发生此错误:“input”必须是包含文件名的单个字符串,系统命令至少包含一个空格。这很酷。但是,我如何“并行”处理所有文件呢?这个选项很好,它工作得很好,但我需要使用R来完成。许多我不使用的计算机没有Linux,最终问题会再次出现。@JoyceMaia关于“并行”处理文件的问题;您将以与代码中相同的方式处理文件:要么读入文件并以某种形式循环处理数据,要么使用一种方法(例如使用
并行
)读入/处理数据。顺便说一句,GNU的CoreUtils(包括
拆分
)是。
library(data.table)

index <- 0
counter <- 0
total <- 0
chunks <- 1000000
fileName <- "myfile"

repeat{
  # With fread file is opened in each iteration
  dataChunk <- fread(input = fileName, nrows=chunks, header=FALSE, fill = TRUE,                 
                          skip = chunks*index, sep=";", col.names=db_colnames)

  # do processing on dataChunk (i.e adding header, converting data type) 

  # Create a new file name and write to it. You can have your own logic for file names
  write.table(dataChunk, file = paste0("file",index))

  #check if file end has been reached and break from repeat
  if(nrow(dataChunk) < chunks){
    break
  }

  #increment the index to read next chunk
  index = index+1

}
split -l 1000000 my_file.txt