【问题标题】:Automating chunking of big data in R using a loop使用循环在 R 中自动分块大数据
【发布时间】:2014-10-14 23:28:32
【问题描述】:

我正在尝试将一个非常大的数据集分成多个块。我的代码如下所示:

#Chunk 1
data <- read.csv("/Users/admin/Desktop/data/sample.csv", header=T, nrow=1000000)
write.csv(data, "/Users/admin/Desktop/data/data1.csv")

#Chunk 2
data <- read.csv("/Users/admin/Desktop/data/sample.csv", header=F, nrow=1000000, skip=1000000)
write.csv(data, "/Users/admin/Desktop/data/data2.csv")

#Chunk 3
data <- read.csv("/Users/admin/Desktop/data/sample.csv", header=F, nrow=1000000, skip=2000000)
write.csv(data, "/Users/admin/Desktop/data/data3.csv")

我的数据集中有数亿行,所以我需要创建很多块,我真的很想自动化这个过程。有没有办法循环这个命令,以便每个后续块自动跳过比前一个块多 1,000,000 行,并且文件保存为“dataN.csv”(N 表示前一个文件的后续数字)?

【问题讨论】:

  • 当然:你试过writing a for loop吗?
  • 试试 LaF 包,尤其是阅读其小插图的块处理部分。

标签: r chunking


【解决方案1】:

下面的方法呢?为了演示,我创建了一个包含两列十行的数据框,并在循环中读取了两次,每次五行,将结果保存为文本文件:

f<-"C:/Users/MyPC/Desktop/"
for(i in 1:2){
    df <- read.table("C:/Users/MyPC/Desktop/df.txt", header=FALSE, nrow=5, skip=5*(i-1))
    file <- paste(f,sep="","df",i,".txt")
    write.table(df,file)
}

【讨论】:

  • 我尝试了您的方法,但收到以下错误消息:Error in type.convert(data[[i]], as.is = as.is[i], dec = dec, na.strings = character(0L)) : invalid multibyte string at '&lt;c9&gt;&lt;fa&gt;&lt;d2&gt;&lt;e2&gt;&lt;bb&gt;&lt;ef&gt;&lt;b0&gt;&lt;e9&gt;&lt;c1&gt;&lt;f7&gt;'
  • 您的数据集包含哪些类型的列?可以提供str(dataset)吗?
  • 第一个版本并不是你想要的。试试编辑后的版本。
【解决方案2】:

对上述答案的一些改进。使用 lapply() 代替 for 循环,使用 data.table::fread() 代替 read.table()。

For 循环与 lapply 有据可查的是,如果可能的话,应该使用 lapply 而不是 for 循环。一个快速的谷歌搜索将显示大量的论点和例子。 lapply 更快,它返回一个列表而不是必须定义一个列表(或其他存储对象),并且它可以很容易地并行运行,因为循环的每次迭代都是一个独立的函数调用,而不是“顶部的循环”等级。”在这种情况下,切换到 lapply 可以节省 7 秒(这相当微不足道,但最好养成好习惯)。

read.csv() 与 data.table::fread() fread() 是对 read.csv() 的主要速度改进(我已经看到了 2-5 倍的加速,具体取决于数据等。here 是一篇文章,显示了大约 15 倍的加速),它旨在处理一些管理任务,例如猜测分隔符。在这种情况下,将 fread() 替换为 read.csv() 时有 15 秒的加速

> # Libraries and options ---------------------------------------------------
> 
> library(dplyr)

> library(data.table)

> # Helper parameters -------------------------------------------------------
> 
> out_dir = "C:/Users/taylor/Dropbox/R_programming/stackoverflow/data"

> obs = 5e5 

> # Create test data --------------------------------------------------------
> 
> test_df = data_frame(
+   x = rnorm(obs), 
+   y = 0.5 * obs + rnorm(length(x), 0, 0.25), 
+   groups = rep(letters[1:5], length.out = length(x))
+ )

> # export
> write.csv(test_df, paste0(out_dir, "/test_df.csv"), row.names = F)

> # clean memory
> rm(test_df)

> gc()
          used (Mb) gc trigger  (Mb)  max used   (Mb)
Ncells  596408 31.9    1907703 101.9  10636178  568.1
Vcells 9301642 71.0   27768113 211.9 218137457 1664.3

> # For loop and read.csv (read.table alias) -------------------------------------
> 
> system.time({
+   
+   for(i in 1:20){  
+     df = read.csv(paste0(out_dir, "/test_df.csv"))
+     write.csv(df, paste0(out_dir, "/test_df_export_original_example_", i, ".csv"), row.names = F)  
+   }  
+   
+ })
   user  system elapsed 
 130.28    2.70  148.60 

> # Lapply and read.csv -----------------------------------------------------
> 
> # clean memory
> rm(df, i)

> gc()
          used (Mb) gc trigger  (Mb)  max used   (Mb)
Ncells  596411 31.9    2185242 116.8  10636178  568.1
Vcells 9301647 71.0   27768113 211.9 218137457 1664.3

> system.time({
+   
+   lapply(1:20, function(i){
+     df = read.csv(paste0(out_dir, "/test_df.csv"))
+     write.csv(df, paste0(out_dir, "/test_df_export_lapply_", i, ".csv"), row.names = F)  
+   })  
+   
+ })
   user  system elapsed 
 123.33    2.07  140.03 

> # Lapply and fread() ------------------------------------------------------
> 
> system.time({
+   
+   lapply(1:20, function(i){
+     df = fread(paste0(out_dir, "/test_df.csv"))
+     write.csv(df, paste0(out_dir, "/test_df_export_lapply_fread_", i, ".csv"), row.names = F)  
+   })  
+   
+ })
   user  system elapsed 
 107.98    2.10  123.36 

【讨论】:

  • 你能用一个例子扩展这个答案吗?为什么它可能比第一个答案有所改进?
  • @alexforrence 进行了编辑。如此挑剔真的没有意义——当有人在收到建议后可以花 5 分钟时间来谷歌 fread 与 read.table 或 lapply 与 for 循环时,我为什么要多花 20 分钟的时间来完善答案那个效果?
  • 基本上,答案应该能够独立存在。相关讨论见答案herehere
猜你喜欢
  • 2016-09-11
  • 2016-02-15
  • 2013-09-05
  • 1970-01-01
  • 2022-01-09
  • 2017-11-11
  • 1970-01-01
  • 2014-03-14
  • 2020-03-21
相关资源
最近更新 更多