【问题标题】:Find difference of two columns in a CSV and store in third column in chunks查找 CSV 中两列的差异并以块的形式存储在第三列中
【发布时间】:2016-12-01 13:23:05
【问题描述】:

我有一个较大的 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 文件。

【问题讨论】:

  • 为什么不能一次读取1M行?那不是那么大。那么它只是一个 df$PTDR &lt;- df$MMSRATE - df$SMSRATE 一次传递。
  • 如果只是 csv 的问题,awk 可能最适合:awk -F "," -v OFS="," 'NR==1{print $0,"PDRATE"} NR&gt;1{end=$3-$4; print $0,end}' your_file.csv
  • @Tensibai 这是给我的要求,即对 csv 中的行块执行列差异操作。所以我无法整体读取整个 csv 文件。你能提出可能的解决方案吗?
  • 所以这是家庭作业,你应该说出来。没有人会在不知道需要满足此要求的情况下回答此要求。
  • @Tensibai 我将在我的帖子中进行必要的更改。

标签: r csv chunks


【解决方案1】:

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

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)

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

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

忽略更改 append、col.names、sep、dec 或 qmethod 的尝试,并发出警告。

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

【讨论】:

  • 警告消息:1:在 write.csv(data_frame, outfile, append = TRUE, col.names = FALSE, : 尝试设置 'append' 被忽略。
  • 追加操作未发生。 Out.csv 仅保存上次迭代中存在的值。
  • 太棒了,非常感谢。作为个人喜好,有没有办法只将 NUM 列读取为字符类类型?我知道通过使用 colClassType='character',我可以将所有列读取为字符串。但我只想将 NUM 列读为字符。有没有办法做到这一点?提前致谢。
  • 在会议中,我认为您可以将列类赋予 read.csv。稍后检查。
  • @Ramkrishna colClasses 可以采用类型向量,每列一个。以这种方式编辑。
【解决方案2】:

我遇到了一个有趣的包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,是处理大文件的非常方便的工具。此外,还允许您对表格输出和其他计算进行分组。您可以通过Cheat sheet了解更多信息

【讨论】:

  • 不要编辑问题来破坏他们的 mcve。 csv 输入完全可以作为 mcve,并且比 post 之类的表格更有用。特别是当 Q 是关于处理 csv 文件时。
  • 编辑后才发现。谢谢。会记住的
猜你喜欢
  • 1970-01-01
  • 2021-09-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-05-02
  • 1970-01-01
  • 2011-01-25
  • 1970-01-01
相关资源
最近更新 更多