代码提速
一、向量化代码
快速的R代码都经常用到三大法宝:逻辑测试、 取子集和元素方式执行。
用到这三大法宝的R代码往往都具有一种特性:代码是向量化的。所谓向量化代码就是指代码可以接受一个含有多个值的向量作为输入,并且同时操作向量中的每一个元素。
函数abs_loop利用for循环对该向量的元素逐一取绝对值。
vec <- c(1,-2,3,4,-5)
abs_loop<-function(vec){
for(i in 1:length(vec)){
if(vec[i]<0){
vec[i]<--vec[i]}
}
vec
}
abs_loop(vec)函数abs_loop利用for循环对该向量的元素逐一取绝对值
vec<-c(1,-3,-7,6)
abs_set<-function(vec){
negs<-vec<0
vec[negs]<-vec[negs]* -1
vec
}
abs_set(vec)使用了逻辑值取子集的方法将所有的负数同时转换成了正数。
首先生成一个包含正数和负数的长向量long,它含有1000万个数值。long<-rep(c(-1,1),5000000)
rep的作用是重复生成某一个值或向量。它的使用方法是,先指定需要重复生成的值或向量,再设定想要重复的次数。
接下来用system.time测量两个函数完成long元素的绝对值转换所需要的时间。
system.time(abs_loop(long))
system.time(abs_set(long))
不要混淆system.time和sys.time,后者的作用是返回当前的系统时间。
二、如何编写向量化代码
要编写向量化代码,可以尝试以下两种方法。
(1)对于程序中的有序步骤,使用向量化的函数来完成。
(2)对于同类情况,使用逻辑值取子集的方式来处理。尝试一次性处理完成一类情况中的所有元素
比如说,vec可以识别出vec向量中所有的负数元素。使用相同的逻辑测试,可以通过逻辑值取子集的方法取出所有的负数值。
vec<-c(1,-2,3,-4,5,-6,7,-8,9,-10)
vec<0
vec[vec<0]
下面这个函数的功能是将一个包含老虎机符号的向量转换成一批新的符号。能尝试将这段代码向量化吗?向量化之后的代码比原代码快了多少?
change_symbols<-function(vec){
for(i in 1:length(vec)){
if(vec[i]=="DD"){
vec[i]<-"joker"
}else if(vec[i]=="C"){
vec[i]<-"ace"
}else if(vec[i]=="7"){
vec[i]<-"king"
}else if(vec[i]=="B")