R语言中的向量化操作

我们在日常的数据分析过程中,经常要进行循环的操作。但是在R语言中,for循环的效率低下,如果是数据量比较大的情况下,可能会花费比较多的时间。因此,我们可以使用向量化操作来代替循环。向量化可以理解为高效的循环。
我们主要讲解基础包中的:

  • lapply
  • sapply
  • apply
  • tapply
  • aggregate
  • doBy::summaryBy
  • split

1.基础包


1.1-lapply(对列表,数据框进行循环)

  • Lapply返回一个列表, 并无视输入变量的类型
(x <- list(a=1:5,b=rnorm(10),c=rnorm(20,1),d=rnorm(100,5)))
lapply(x,mean)
结果为一个列表:
$a
[1] 3

$b
[1] 0.01155605

$c
[1] 1.204898

$d
[1] 5.086932

1.2-sapply(简化lapply函数返回的结果)

  • 若结果是一个list,且每个元素长度为1,则会返回一个
    向量
  • 若结果是一个list,且每个元素长度为大于1,则会返回
    一个矩阵
  • 若其他复杂的结果,会返回一个向量
> (x <- list(a=1:5,b=rnorm(10),c=rnorm(20,1),d=rnorm(100,5)))
> sapply(x,mean)
         a          b          c          d 
3.00000000 0.01155605 1.20489776 5.08693239 

1.3-apply

此函数经常被用于对矩阵的行或列进行指定目的的循环
• 可以被用于多个数组的循环
• 该函数作用于一行进行循环

str(apply)
function (X, MARGIN, FUN, ...)

• X 是一个数组
• MARGIN 参数是一个数字向量,在适用与矩阵时,1表示行,2表示列,也可以是列名
• FUN 是适用循环的函数
• ... 表示其他参数

(x<-matrix(rnorm(24),4,6))
apply(x,1,sum) #对行
apply(x,2,mean) #对列

1.4 tapply(适用于数据框的一个连续变量做分组描述统计)

> (x<-c(rnorm(10),runif(10),rnorm(10,1)))
 [1] -0.8483055 -1.0072368  0.2642566  0.2944829 -2.0119795  0.4597912  0.2354388 -1.0045856  0.6877217  0.6311278  0.3575496
[12]  0.2112962  0.8207528  0.2901692  0.9472960  0.2700287  0.5492559  0.7635016  0.6240591  0.9337211 -2.1545025  2.5330094
[23]  1.2496200  1.4399020 -1.5014259  2.0208022  1.3946920  2.8143463  3.1911815  1.5542655
> (group <- rep(1:3,each=10))
 [1] 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 3 3 3 3 3 3 3 3 3
> (a <- data.frame(x=x,group=group))
            x group
1  -0.8483055     1
2  -1.0072368     1
3   0.2642566     1
4   0.2944829     1
5  -2.0119795     1
6   0.4597912     1
7   0.2354388     1
8  -1.0045856     1
9   0.6877217     1
10  0.6311278     1
11  0.3575496     2
12  0.2112962     2
13  0.8207528     2
14  0.2901692     2
15  0.9472960     2
16  0.2700287     2
17  0.5492559     2
18  0.7635016     2
19  0.6240591     2
20  0.9337211     2
21 -2.1545025     3
22  2.5330094     3
23  1.2496200     3
24  1.4399020     3
25 -1.5014259     3
26  2.0208022     3
27  1.3946920     3
28  2.8143463     3
29  3.1911815     3
30  1.5542655     3
> tapply(a$x,a$group,mean)
         1          2          3 
-0.2299289  0.5767630  1.2541891 
  • Note:tapply只能针对一个分组变量进行分组统计,且只能针对一个连续变量
    执行下列就会出错
> tapply(mtcars[,c('mpg','hp','wt')],mtcars$am,summary)
Error in tapply(mtcars[, c("mpg", "hp", "wt")], mtcars$am, summary) : 
  参数的长度必需相同

使用之前我们学过的东西进行改进的话可以酱紫:

> apply(mtcars[,c("am","mpg","hp","wt")],2,function(x) tapply(x,mtcars$am,mean))
  am      mpg       hp       wt
0  0 17.14737 160.2632 3.768895
1  1 24.39231 126.8462 2.411000

但是依然还是有缺陷,就是只能对一个分组变量,不能同时对多个变量进行
接下来我们讲下怎么弥补这个缺陷:

  • 方案1:利用aggregate函数
> Myfun <- function(x) c(mean=mean(x),sd=sd(x))
> aggregate(mtcars[,c("mpg","hp","wt")],by=list(am=mtcars$am,cyl=mtcars$cyl),Myfun)
  am cyl   mpg.mean     mpg.sd   hp.mean     hp.sd   wt.mean     wt.sd
1  0   4 22.9000000  1.4525839  84.66667  19.65536 2.9350000 0.4075230
2  1   4 28.0750000  4.4838599  81.87500  22.65542 2.0422500 0.4093485
3  0   6 19.1250000  1.6317169 115.25000   9.17878 3.3887500 0.1162164
4  1   6 20.5666667  0.7505553 131.66667  37.52777 2.7550000 0.1281601
5  0   8 15.0500000  2.7743959 194.16667  33.35984 4.1040833 0.7683069
6  1   8 15.4000000  0.5656854 299.50000  50.20458 3.3700000 0.2828427
  • 方案2:利用doBy包中的summaryBy函数
> doBy::summaryBy(mpg+hp+wt~am+cyl,data = mtcars,FUN=Myfun)
  am cyl mpg.mean    mpg.sd   hp.mean    hp.sd  wt.mean     wt.sd
1  0   4 22.90000 1.4525839  84.66667 19.65536 2.935000 0.4075230
2  0   6 19.12500 1.6317169 115.25000  9.17878 3.388750 0.1162164
3  0   8 15.05000 2.7743959 194.16667 33.35984 4.104083 0.7683069
4  1   4 28.07500 4.4838599  81.87500 22.65542 2.042250 0.4093485
5  1   6 20.56667 0.7505553 131.66667 37.52777 2.755000 0.1281601
6  1   8 15.40000 0.5656854 299.50000 50.20458 3.370000 0.2828427
  • 方案3:利用dplyr包
dplyr::group_by(mtcars,am,cyl) %>% dplyr::summarise(
mpg.mean=mean(mtcars$mpg,na.rm = TRUE),hp.mean=mean(mtcars$hp,na.rm = T))

1.5-split

split 用于使某向量或对象分为指定数目的列表,指
定数目的组由因子列表确定

str(split)
function (x, f, drop = FALSE, ...)

• X是一个向量或数据框
• F是一个因子或因子列表
• Drop表示空因子水平是否舍弃

> accepts <- mtcars[,c("am","mpg","wt","hp")]
>( s<-split(accepts,accepts$am))
$`0`
                    am  mpg    wt  hp
Hornet 4 Drive       0 21.4 3.215 110
Hornet Sportabout    0 18.7 3.440 175
Valiant              0 18.1 3.460 105
Duster 360           0 14.3 3.570 245
Merc 240D            0 24.4 3.190  62
Merc 230             0 22.8 3.150  95
Merc 280             0 19.2 3.440 123
Merc 280C            0 17.8 3.440 123
Merc 450SE           0 16.4 4.070 180
Merc 450SL           0 17.3 3.730 180
Merc 450SLC          0 15.2 3.780 180
Cadillac Fleetwood   0 10.4 5.250 205
Lincoln Continental  0 10.4 5.424 215
Chrysler Imperial    0 14.7 5.345 230
Toyota Corona        0 21.5 2.465  97
Dodge Challenger     0 15.5 3.520 150
AMC Javelin          0 15.2 3.435 150
Camaro Z28           0 13.3 3.840 245
Pontiac Firebird     0 19.2 3.845 175

$`1`
               am  mpg    wt  hp
Mazda RX4       1 21.0 2.620 110
Mazda RX4 Wag   1 21.0 2.875 110
Datsun 710      1 22.8 2.320  93
Fiat 128        1 32.4 2.200  66
Honda Civic     1 30.4 1.615  52
Toyota Corolla  1 33.9 1.835  65
Fiat X1-9       1 27.3 1.935  66
Porsche 914-2   1 26.0 2.140  91
Lotus Europa    1 30.4 1.513 113
Ford Pantera L  1 15.8 3.170 264
Ferrari Dino    1 19.7 2.770 175
Maserati Bora   1 15.0 3.570 335
Volvo 142E      1 21.4 2.780 109
> sapply(s, function(x) lapply(x[,2:3],function(col) mean(col,na.rm = T)))
    0        1       
mpg 17.14737 24.39231
wt  3.768895 2.411  
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,313评论 6 496
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,369评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 159,916评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,333评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,425评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,481评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,491评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,268评论 0 269
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,719评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,004评论 2 328
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,179评论 1 342
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,832评论 4 337
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,510评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,153评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,402评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,045评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,071评论 2 352

推荐阅读更多精彩内容