说到R,人们除了赞美它漂亮简洁的做图功能外,就是抱怨它的运行速度问题。做为常规使用,好比数据整理分析,统计计算或者做图等,或许没有感受到它的运行速度有问题。可是若是数据量很大,像基因组数据,那么运行起来就尤为慢了。特别是对于循环语句,犹如老牛拉破车,因此在数据量很大的状况下,尽可能不要在R中使用循环语句。html
那么循环语句在R中会慢到什么地步?咱们经过R语言和C语言的比较就能看出一些端倪。编程
咱们假设有这么两个数据框,以下图。咱们要判断每个pos中的数据(4,15,19,27)是否落在第一个数据框的数据区间内(2-5,7-11,17-20,23-28,32-39)。这样咱们就会用到两个嵌套for循环,对第二个数据框中的每个数,依次比对第一个数据框中的每个数据段。app
首先咱们使用随机数生成这么两个模拟数据框编程语言
set.seed(111) creat_test <- function(len, seg){ x <- sample(1:len,2*seg, replace = F) x <- x[order(x)] start = numeric() end = numeric() for (i in seq(1,length(x),2)){ start <- c(start,x[i]) end <- c(end,x[i+1]) } test_df <- data.frame("start" = start, "end" = end) return(test_df) } # create first data frame, using length = 7,000,000, segments = 20,000 test_data <- creat_test(7000000, 200000) #object.size(test_data) -- 3.2Mb # create second data frame, sequence data sequence <- data.frame('x' = sample(1:7000000, 400, replace = F)) sequence$x <- sequence[order(sequence$x),]
自此,咱们有了两个测试数据框,第一个test_data里面有20万条观测,第二个sequence里面有400个观测,那么咱们首先经过R中的for循环来判断这400个观测时候落在来第一个数据框中数据段内。ide
# using R loop to see if sequence in test_data range R_time <- function(sequence, test_data){ num_in <- 0 for (i in 1:nrow(sequence)){ for (j in 1:nrow(test_data)){ if (sequence[i,1] > test_data[j,1] & sequence[i,1] < test_data[j,2]){ num_in <- num_in + 1 break } } } print(num_in) } system.time(R_time(sequence,test_data))
这段代码中两个for循环,大概运行来:函数
下面咱们看一看在C语言中完成这段代码须要多长时间。本人并不了解C语言,可是Rcpp包提供了在R中写C代码的可能,因此使用Rcpp完成上述功能以下:oop
# using Rcpp library(Rcpp) cppFunction(' int Rcpp_time(DataFrame sequence, DataFrame test_data){ IntegerVector start=test_data["start"]; IntegerVector end=test_data["end"]; IntegerVector pos=sequence["x"]; int seq_size=sequence.nrow(); int test_size=test_data.nrow(); int num_in=0; for(int i=0; i<=seq_size; i++){ for(int j=0; j<=test_size; j++){ if(pos[i]>start[j] && pos[i]<end[j]){ num_in++; break; } } } return num_in; } ') system.time(Rcpp_time(sequence,test_data))
而这段代码的运行时间仅仅为:测试
能够看出,一样的一段代码,获得相同的结果,在R中运行的时间是在C中运行时间的数万倍!什么概念:code
在R中你要等1个多小时,在C中你在1秒内就完成!orm
固然这也很好理解,毕竟相对于C来说,R属于高级编程语言,并且是解释型语言,没有C的编译过程,因此R会针对每个for循环一一执行,这也下降了速度。
那么问题来了,应该怎样提升R的运行速度呢?
一、避免使用for循环,尤为是数据量特别大的时候;
二、避免数据的复制,使用%>%之类的管道操做;
三、使用一些更快的R包处理数据,好比data.table;
四、使用apply、lapply等之类的函数代替for;
五、使用Rcpp编写C语言函数;
六、使用多核并行计算(能够经过lapply来实现);
能够参考http://adv-r.had.co.nz/Performance.html