优化对于嵌套的循环,如果R中

问题描述:

我想多个CSV文件合并成一个单一的数据帧,并试图操纵使用for循环生成的数据帧。结果数据帧的行数可能在1,500,000到2,000,000之间。优化对于嵌套的循环,如果R中

我使用了相同下面的代码。

setwd("D:/Projects") 
library(dplyr) 
library(readr) 
merge_data = function(path) 
{ 
    files = dir(path, pattern = '\\.csv', full.names = TRUE) 
    tables = lapply(files, read_csv) 
    do.call(rbind, tables) 
} 


Data = merge_data("D:/Projects") 
Data1 = cbind(Data[,c(8,9,17)],Category = "",stringsAsFactors=FALSE) 
head(Data1) 

for (i in 1:nrow(Data1)) 
{ 
    Data1$Category[i] = "" 
    Data1$Category[i] = ifelse(Data1$Days[i] <= 30, "<30", 
         ifelse(Data1$Days[i] <= 60, "31-60", 
         ifelse(Data1$Days[i] <= 90, "61-90",">90")))  

} 

但是代码运行时间很长。有更好更快的方式来做同样的操作吗?

我们可以通过freaddata.table开始阅读,然后使用cut/findInterval进行更优化。当它在多内核运行,这将变得更加明显,其中fread利用所有的节点和服务器节点上执行并行

library(data.table) 
merge_data <- function(path) { 
    files = dir(path, pattern = '\\.csv', full.names = TRUE) 
    rbindlist(lapply(files, fread, select = c(8, 9, 17))) 
} 

Data <- merge_data("D:/Projects") 
Data[, Category := cut(Data1, breaks = c(-Inf, 30, 60, 90, Inf), 
     labels = c("<=30", "31-60", "61-90", ">90"))] 
+1

非常感谢!代码工作正常,运行时间少于几秒钟:) –

您已经在使用dplyr,那么为什么不只是:

Data = merge_data("D:/Projects") %>% 
    select(8, 9, 17) %>% 
    mutate(Category = cut(Days, 
         breaks = c(-Inf, 30, 60, 90, Inf), 
         labels = c("<=30", "31-60", "61-90", ">90")) 

Akrun确实是正确的,FREAD实质上更快read.csv。

然而,除了他的职位,我也补充一点,你的循环是完全不必要的。他用我不熟悉的cut/findInterval替换它。虽然在简易R编程方面,对循环时,在计算一些因素被排改变是必要的。但是,在您的代码中,情况并非如此,并且不需要for循环。

基本上你正在运行的计算达200万次时,你只需要运行一次在列计算。

你可以像这样的东西取代您的for循环:

Data1$category = ifelse(Data1$Days <= 30, "<=30", 
       ifelse(Data1$Days <= 60, "31-60", 
       ifelse(Data1$Days <= 90, "61-90",">90"))) 

,你的代码将waaaaaay更快地运行