R语言加快运算的几种方法

时间:2024-04-13 18:55:23

背景

提升R代码运行速度并不需要很高级的优化技术, 例如代码并行化, 使用数据库, 使用c++等. 实际上, 通过简单的操作, 就能够是R的运算速度显著的加快, 下面介绍几种方法.

1, 向量化

R语言允许用户进行向量化编程, 这样速度更快.

比如我们计算100万随机数, 计算他们的平方, 这里使用两种方法: 第一种, for循环; 第二种, 向量化

set.seed(123)
dat= rnorm(1000000)

for循环

system.time({
    dd = NULL
    for(i in 1:length(dat)){
        dd[i] = dat[i]^2
    }
    })
   user  system elapsed 
   0.31    0.03    0.35 
head(dat);head(dd)
  1. -0.560475646552213
  2. -0.23017748948328
  3. 1.55870831414912
  4. 0.070508391424576
  5. 0.129287735160946
  6. 1.71506498688328
  1. 0.314132950378121
  2. 0.0529816766648255
  3. 2.4295716085976
  4. 0.00497143326128122
  5. 0.016715318463047
  6. 2.94144790923295

直接在原向量上计算平方

system.time({
    dd2 =dat^2
    })
   user  system elapsed 
      0       0       0 
head(dat);head(dd2)
  1. -0.560475646552213
  2. -0.23017748948328
  3. 1.55870831414912
  4. 0.070508391424576
  5. 0.129287735160946
  6. 1.71506498688328
  1. 0.314132950378121
  2. 0.0529816766648255
  3. 2.4295716085976
  4. 0.00497143326128122
  5. 0.016715318463047
  6. 2.94144790923295

速度由0.3s到0.02s

2, 预分配内存

R语言是动态分布内存的, 不需要预先生成变量, 可以直接使用. 这种方法比较简单, 但是数据量大时, 会影响速度. 所以在使用变量时, 提前声明变量的大小, 会提升速度

不预先分布内存

这个程序, 不知道dat的长度是多少, 因此是动态的内存结构.

N = 1e5;N

1e+05

system.time({
    dat =1 
    for(i in 2:N){
        dat = c(dat,dat[i-1]+sample(1:2,size = 1))
    }
    })
   user  system elapsed 
   8.88    0.15    9.07 

预先分配内存

dat的长度是1e5, 因此我们可以生成这一个为0的向量, 这样他的内存就固定了

N = 1e4;N
dat = rep(0,N)

10000

system.time({
    dat =1 
    for(i in 2:N){
        dat = c(dat,dat[i-1]+sample(1:2,size = 1))
    }
    })
   user  system elapsed 
   0.14    0.00    0.14 

可以看到, 时间由7.5s降到0.11s

3, 使用apply函数代替for循环

apply函数及其变种:

  • lapply
  • sapply
  • tapply

如果各个迭代之间相互独立, 那么apply函数是可以代替for循环的

for循环

set.seed(123)
dat= rnorm(1000000)
system.time({
    dd = NULL
    for(i in 1:length(dat)){
        dd[i] = dat[i]^2
    }
    })
   user  system elapsed 
   0.28    0.00    0.28 
square = function(x){
    return(x^2)
}

system.time({tt = lapply(dat, FUN=square)})
   user  system elapsed 
   1.00    0.00    1.02 
t = rep(0,length(dat))
system.time({t = lapply(dat, FUN=square)})
   user  system elapsed 
   0.62    0.03    0.66 

4, 使用matrix而不是data.table

在矩阵运算时, 尽量转化为matrix格式

使用matrix

dat = matrix(rnorm(1e4*1000),1e4,1000)

dd = as.data.frame(dat)
system.time( rowSums(dd))
   user  system elapsed 
   0.05    0.00    0.05 

使用data.frmae

system.time( rowSums(dat))
   user  system elapsed 
   0.04    0.00    0.03 

R语言加快运算的几种方法