我們在日常的數(shù)據(jù)分析過程中,經(jīng)常要進(jìn)行循環(huán)的操作。但是在R語言中,for循環(huán)的效率低下,如果是數(shù)據(jù)量比較大的情況下,可能會花費(fèi)比較多的時間。因此,我們可以使用向量化操作來代替循環(huán)。向量化可以理解為高效的循環(huán)。
我們主要講解基礎(chǔ)包中的:
- lapply
- sapply
- apply
- tapply
- aggregate
- doBy::summaryBy
- split
1.基礎(chǔ)包
1.1-lapply(對列表,數(shù)據(jù)框進(jìn)行循環(huán))
- Lapply返回一個列表, 并無視輸入變量的類型
(x <- list(a=1:5,b=rnorm(10),c=rnorm(20,1),d=rnorm(100,5)))
lapply(x,mean)
結(jié)果為一個列表:
$a
[1] 3
$b
[1] 0.01155605
$c
[1] 1.204898
$d
[1] 5.086932
1.2-sapply(簡化lapply函數(shù)返回的結(jié)果)
- 若結(jié)果是一個list,且每個元素長度為1,則會返回一個
向量 - 若結(jié)果是一個list,且每個元素長度為大于1,則會返回
一個矩陣 - 若其他復(fù)雜的結(jié)果,會返回一個向量
> (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
此函數(shù)經(jīng)常被用于對矩陣的行或列進(jìn)行指定目的的循環(huán)
? 可以被用于多個數(shù)組的循環(huán)
? 該函數(shù)作用于一行進(jìn)行循環(huán)
str(apply)
function (X, MARGIN, FUN, ...)
? X 是一個數(shù)組
? MARGIN 參數(shù)是一個數(shù)字向量,在適用與矩陣時,1表示行,2表示列,也可以是列名
? FUN 是適用循環(huán)的函數(shù)
? ... 表示其他參數(shù)
(x<-matrix(rnorm(24),4,6))
apply(x,1,sum) #對行
apply(x,2,mean) #對列
1.4 tapply(適用于數(shù)據(jù)框的一個連續(xù)變量做分組描述統(tǒng)計(jì))
> (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只能針對一個分組變量進(jìn)行分組統(tǒng)計(jì),且只能針對一個連續(xù)變量
執(zhí)行下列就會出錯
> tapply(mtcars[,c('mpg','hp','wt')],mtcars$am,summary)
Error in tapply(mtcars[, c("mpg", "hp", "wt")], mtcars$am, summary) :
參數(shù)的長度必需相同
使用之前我們學(xué)過的東西進(jìn)行改進(jìn)的話可以醬紫:
> 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
但是依然還是有缺陷,就是只能對一個分組變量,不能同時對多個變量進(jìn)行
接下來我們講下怎么彌補(bǔ)這個缺陷:
- 方案1:利用aggregate函數(shù)
> 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函數(shù)
> 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 用于使某向量或?qū)ο蠓譃橹付〝?shù)目的列表,指
定數(shù)目的組由因子列表確定
str(split)
function (x, f, drop = FALSE, ...)
? X是一個向量或數(shù)據(jù)框
? 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