【问题标题】:R: Split and write very large data frame into slicesR:将非常大的数据帧拆分并写入切片
【发布时间】:2019-11-25 16:38:21
【问题描述】:

我在 R 中有一个大数据框 my_df,其中包含 1983000 记录。下面几行示例代码从25001开始取1000行的chunk,做一些处理,将处理后的数据写入一个文件到本地磁盘。

my_df1 <- my_df[25001:26000,]
my_df1$end <- as.POSIXct(paste(my_df1$end,"23:59",sep = ""))
my_df1$year <- lubridate::year(my_df1$start)
str_data <- my_df1
setwd("path_to_local_dir/data25001_26000")
write.table(str_data, file = "data25001-26000.csv",row.names = F,col.names = F,quote = F)

类似这样的:

my_df2 <- my_df[26001:27000,]
...

我希望自动执行此任务,以便处理 1000 条记录的块并将其写入新目录。关于如何做到这一点的任何建议?

【问题讨论】:

    标签: r dataframe slice


    【解决方案1】:

    您可以先将分组变量添加到数据中(例如,识别每 1000 行),然后使用 d_ply() 拆分数据并写入文件。

    df <- data.frame(var=runif(1000000))
    df$fold <- cut(seq(1,nrow(df)),breaks=100,labels=FALSE)
    
    df %>% filter(fold<=2) %>% # only writes first two files
      d_ply(.,.(fold), function(i){
        # make filenames 'data1.csv', 'data2.csv'
        write_csv(i,paste0('data',distinct(i,fold),'.csv')) 
        })
    

    【讨论】:

      【解决方案2】:

      这类似于@Parfait,但从函数中提取了很多东西。具体来说,它会创建整个数据集的副本,然后执行时间操作功能。

      my_df1 <- my_df
      my_df1$end <- as.POSIXct(paste(my_df1$end,"23:59",sep = ""))
      my_df1$year <- lubridate::year(my_df1$start)
      
      lapply(seq(25001, nrow(my_df1), by = 1000),
             function(i) write.table(my_df1[i:i+1000-1,]
                                     , file = paste0('path_to_logal_dir/data'
                                                     , i, '-', i+1000-1, '.csv')
                                     ,row.names = F,col.names = F,quote = F)
      )
      

      对我来说,我可能会这样做:

      write.table(my_df1, file = ...)
      

      并完成它。我看不出拆分它的好处 - 100 万行确实不算多。

      【讨论】:

        【解决方案3】:

        这是我执行切片循环的代码:

        step1 = 1000
        runto = nrow(my_df)
        nsteps = ceiling(runto/step1)
        for( part in seq_len(nsteps) ) { # part = 1
            cat( part, 'of', nsteps, '\n')
            fr = (part-1)*step1 + 1
            to = min(part*step1, runto)
        
            my_df1 = my_df[fr:to,]
            # ...
            write.table(str_data, file = paste0("data",fr,"-",to,".csv"))
        }
        rm(part, step1, runto, nsteps, fr, to)
        

        【讨论】:

          【解决方案4】:

          考虑在一个函数中概括您的过程,data_to_disk,并使用像 lapply 这样的迭代器方法调用函数,并为随后的每千位传递一个带有 seq() 的整数序列。另外,合并一个动态目录创建(但可能将所有 1,000 多个文件转储到一个目录而不是 1,000 多个目录中?)。

          data_to_disk <- function(num) {
             str_data <- within(my_df[num:(num + 999)], {
                             end <- as.POSIXct(paste0(end, "23:59"))
                             year <- lubridate::year($start)
                         })
          
             my_dir <- paste0("path_to_local_dir/data", num, "_", num + 999)
             if(!dir.exists(my_dir)) dir.create(my_dir)
          
             write.table(str_data, file = paste0(my_dir, "/", "data", num, "-", num + 999, ".csv"), 
                         row.names = FALSE, col.names = FALSE, quote = FALSE)
             return(my_df)
          }
          
          seqs <- seq(25001, nrow(my_df), by=1000)
          head(seqs)
          # [1] 25001 26001 27001 28001 29001 30001
          tail(seqs)
          # [1] 1977001 1978001 1979001 1980001 1981001 1982001    
          
          # LIST OF 1,958 DATA FRAMES
          df_list <- lapply(seqs, data_to_disk)
          

          【讨论】:

            猜你喜欢
            • 2018-11-29
            • 2019-06-16
            • 2017-01-22
            • 1970-01-01
            • 2021-04-02
            • 2013-07-24
            • 1970-01-01
            • 1970-01-01
            • 2019-09-20
            相关资源
            最近更新 更多