查找 CSV 中两列的差异并分块存储在第三列中

Find difference of two columns in a CSV and store in third column in chunks

我有一个很大的 CSV 文件(大于 6GB)。文件预览如下:

ID,NUM,MMSRATE,SMSRATE,DATARATE
1,0100000109,623,233,331
2,0200000109,515,413,314
3,0600000109,611,266,662
4,0700000109,729,490,927
5,0800000109,843,637,736
6,0600000109,578,367,875

我想找到 MMSRATE 和 SMSRATE 的区别,并将其存储在同一个 csv 文件的新列 PDRATE 中。预览如下:

ID,NUM,MMSRATE,SMSRATE,DATARATE,PDRATE
1,0100000109,623,233,333,390
2,0200000109,515,413,314,102

我有大约 100 万行。我想读取块中的行(比如 20000),执行差异操作,然后将其写入输出 CSV 文件,然后读取接下来的 20000 行,对其执行操作并将其写入输出 CSV 文件等.

我写了一个代码来读取块中的行(为简单起见,2 行),但我无法在我的脚本中执行 2 列的差异。代码如下:

chunk_size <- 2
con  <- file("input.csv", open = "r")
data_frame <- read.csv(con,nrows = chunk_size,quote="",header = TRUE,)
header <- names(data_frame)
print(header)
print(data_frame)
if(nrow(data_frame) == chunk_size) {
 repeat {
   data_frame <- read.csv(con,nrows = chunk_size, header = FALSE, quote="")
   names(data_frame)<-c(header)
   print(header)
   print(data_frame)
   if(nrow(data_frame) < chunk_size) {
     break
   }
 }
}

close(con)

我对 Rscript 还很陌生。我是 运行 Windows 中的 R Studio IDE。

注意:NUM 列中的前导零应保留在输出 CSV 文件中。请注意,要求我处理 CSV 中的 CHUNKS 行而不是整个 CSV 文件。

我发现了一个有趣的包 chunked

解决方案 1

require(chunked)
data <- read_csv_chunkwise("Test.csv") %>% mutate(diff = MMSRATE - SMSRATE)

     ID       NUM MMSRATE SMSRATE DATARATE  diff
  (int)     (int)   (int)   (int)    (int) (int)
1     1 100000109     623     233      331   390
2     2 200000109     515     413      314   102
3     3 600000109     611     266      662   345
4     4 700000109     729     490      927   239
5     5 800000109     843     637      736   206
6     6 600000109     578     367      875   211

您可以指定块大小,请阅读文档。

解决方案 2

如果您打算使用 datatable

使用 fread 读取您的 csv 文件

require(data.table)
mydata <- fread("file.csv", sep = ",", header= TRUE)

fread 创建一个 data.table

那么,你所要做的就是

mydata [ ,`:=`(Diffcol = MMSRATE-SMSRATE)]
mydata 

 ID        NUM MMSRATE SMSRATE DATARATE Diffcol
1:  1 0100000109     623     233      331     390
2:  2 0200000109     515     413      314     102
3:  3 0600000109     611     266      662     345
4:  4 0700000109     729     490      927     239
5:  5 0800000109     843     637      736     206
6:  6 0600000109     578     367      875     211

注:datatable, is a very handly tool to work with large files. Also, allows you to group table output, and other calculations as well. You can learn more from this Cheat sheet

如果我做对了,请先创建输出文件,然后进行更改并将结果写入输出,并在每次迭代时追加。

chunk_size <- 2
con  <- file("input.csv", open = "r")
data_frame <- read.csv(con,nrows = chunk_size,quote="",colClasses = c("integer","character","integer","integer","integer"), header = TRUE,)
header <- names(data_frame)

outfile="out.csv"
data_frame$PDRATE <- data_frame$MMSRATE - data_frame$SMSRATE
write.csv(data_frame,outfile,row.names=FALSE)

if(nrow(data_frame) == chunk_size) {
 repeat {
   data_frame <- read.csv(con,nrows = chunk_size, colClasses = c("integer","character","integer","integer","integer"), header = FALSE, quote="")
   names(data_frame)<-c(header)

   data_frame$PDRATE <- data_frame$MMSRATE - data_frame$SMSRATE
   # note parameters, append=TRUE and col.names=FALSE
   write.table(data_frame,outfile,sep=",",append=TRUE,qmethod="double",col.names=FALSE,row.names=FALSE) 

   if(nrow(data_frame) < chunk_size) {
     break
   }
 }
}

close(con)

理解上面的代码留作练习:)

评论后的旁注:您不能附加 write.csv,文档状态:

Attempts to change append, col.names, sep, dec or qmethod are ignored, with a warning.

您必须使用 write.table 并指定分隔符和 qmethod 以匹配 write.csv 默认值。