马恩驰:R向量化运算

一、背景

当今社会,数据量剧增让我们越来越关注计算或算法的效率。“并行和分布式”计算是目前主流的能有效提升计算效率的方法,但学习及实施成本较高。所以,向量化运算对于提升计算效率是个不错的选择。作为并行计算的先驱,向量化运算在提升计算效率的同时,也能一定程度上培养数据分析人员的结构化思维。

向量化计算是一种特殊的并行计算的方式,相比于一般程序在同一时间只执行一个操作的方式,它可以在同一时间执行多次操作,通常是对不同的数据执行同样的一个或一批指令,或者说把指令应用于一个数组/向量(from wikipedia);在R中,向量是R的基本运算对象,当你对一个向量计算时,R会对每个元素进行分别处理,最终结果以向量的形式输出,向量化运算在R中有很广泛的应用场景。

二、应用场景

应用场景很大程度上决定我们知识的储备和工具的选择,总结了一下,向量化运算在R中的应用场景主要有以下三点:

  1. 向量的取值与赋值
  2. apply系列函数在数据处理中的应用
  3. 矩阵运算

向量的取值与赋值:这部分应用范围较广,针对较大的数据,如果把向量化运算的思维融入抽样当中,也能明显提升抽样效率,向量的赋值最常见的应用是做缺失值的填补,以上两个应用时数据挖掘的基本功,好的模型需要高质量的数据,高质量的数据需要花精力去清洗。

向量化运算最熟悉的莫过于apply系列函数,这部分函数主要包括:apply,lapply,sapply,tapply,aggreate,by,这几个函数比较基础的向量化运算函数。当然也有Hadley Wickham两个包plyr和reshape,能很容易实现以上函数的功能。 矩阵运算的重要程度相比都很清楚,R也一直提倡做矩阵运算,特别是在文本挖掘和图形处理中的稀疏矩阵处理,向量化运算能大幅提升运算的效率;

三、实例介绍

这个部分主要简单介绍一下前面说过的几个向量化运算函数,然后了解一下plyr包(通过Rstudio镜像获取的下载R包数据发现这个包的下载量一直是第一);

1.apply:对矩阵/数组的行或列应用函数


#生成4*4的矩阵
M <- matrix(seq(1,16), 4, 4)
#对行求和
apply(M, 1, sum)
[1] 120 128 136 144
#分别对行和列汇总
apply(M, c(1,2), sum)
     [,1] [,2] [,3] [,4]
[1,]   18   26   34   42
[2,]   20   28   36   44
[3,]   22   30   38   46
[4,]   24   32   40   48

#注:对于矩阵还可以用colMeansrowMeanscolSumsrowSums做行列运算

2.lapply:对列表应用函数,返回列表

x <- list(a = 1, b = 1:3, c = 10:100) 
lapply(x, FUN = sum) 
$a 
[1] 1
$b 
[1] 6
$c 
[1] 5005

3.sapply:对列表应用函数,返回向量,这个比较常用,等价于unlist(lapply(…)),用lapply计算,然后把结果变为向量;

x <- list(a = 1, b = 1:3, c = 10:100)
sapply(x, FUN = sum)   
a    b    c    
1    6 5005
unlist(lapply(x,sum))
a    b    c    
1    6 5005   

4.tapply:对各因子应用函数(也就是分组计算),这个也常用;

x <- 1:20
y <- factor(rep(letters[1:5], each = 4))
tapply(x, y, sum)  
a  b  c  d  e  
10 26 42 58 74 

5.aggreate:split-apply-combine,拆分成子集,分别计算合并结果输出;

testDF <- data.frame(v1 = c(1,3,5,7,8,3,5,NA,4,5,7,9),
                     v2 = c(11,33,55,77,88,33,55,NA,44,55,77,99) )
by1 <- c("red", "blue", 1, 2, NA, "big", 1, 2, "red", 1, NA, 12)
by2 <- c("wet", "dry", 99, 95, NA, "damp", 95, 99, "red", 99, NA, NA)
aggregate(x = testDF, by = list(by1, by2), FUN = "mean")
Group.1 Group.2 v1 v2
1       1      95  5 55
2       2      95  7 77
3       1      99  5 55
4       2      99 NA NA
5     big    damp  3 33
6    blue     dry  3 33
7     red     red  4 44
8     red     wet  1 11

更简洁易用的plyr包

以上几个函数在实际应用中比较容易混淆,针对输入对象与输出对象应该应用什么函数,见下图:

1

坦白说,以上函数不太容易记住,再来看一下plyr的函数,取输入输出对象的第一个字母+ply;通俗易懂;

2

以常用的ddply函数为例做演示:


#以mtcars数据为例
str(mtcars)
'data.frame':	32 obs. of  11 variables:
 $ mpg : num  21 21 22.8 21.4 18.7 18.1 14.3 24.4 22.8 19.2 ...
 $ cyl : num  6 6 4 6 8 6 8 4 4 6 ...
 $ disp: num  160 160 108 258 360 ...
 $ hp  : num  110 110 93 110 175 105 245 62 95 123 ...
 $ drat: num  3.9 3.9 3.85 3.08 3.15 2.76 3.21 3.69 3.92 3.92 ...
 $ wt  : num  2.62 2.88 2.32 3.21 3.44 ...
 $ qsec: num  16.5 17 18.6 19.4 17 ...
 $ vs  : num  0 0 1 1 0 1 0 1 1 1 ...
 $ am  : num  1 1 1 0 0 0 0 0 0 0 ...
 $ gear: num  4 4 4 3 3 3 3 4 4 4 ...
 $ carb: num  4 4 1 1 2 1 4 2 2 4 ...
#计算每个气缸水平下,mpg的均值和标准差
ddply(mtcars,"cyl",summarise,mean.mpg=mean(mpg),sd.mpg=sd(mpg))
 cyl mean.mpg   sd.mpg
1   4 26.66364 4.509828
2   6 19.74286 1.453567
3   8 15.10000 2.560048

注:数据量比较大时,plyr包的运算效率不理想,曾经用ddply处理一个347万*9的数据框,半个小时没出结果,后来我就放弃了;

plyr上手比较快,结合reshape,掌握部分函数,基本就可以远离EXCEL透视表了,想接着往下走也很容易。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值