一、行列求和、平均值和頻度
rowSums, colSums, rowMeans, colMeans 可以簡單理解爲按行或列求和或求均值,table把數字或字符當成因子統計頻度,都相當簡單:
- > a <- array(rep(1:3, each=3), dim=c(3,3))
- > a
- [,1] [,2] [,3]
- [1,] 1 2 3
- [2,] 1 2 3
- [3,] 1 2 3
- > rowSums(a)
- [1] 6 6 6
- > colSums(a)
- [1] 3 6 9
- > table(a)
- a
- 1 2 3
- 3 3 3
對於多維數組,rowSums, colSums, rowMeans, colMeans的使用稍爲複雜點。它們的參數爲:
- colSums (x, na.rm = FALSE, dims = 1)
- rowSums (x, na.rm = FALSE, dims = 1)
- colMeans(x, na.rm = FALSE, dims = 1)
- rowMeans(x, na.rm = FALSE, dims = 1)
其中dims爲整數,表示哪個或哪些維數被看做行或列,對於row統計函數,dims+1及以後的維度被看做行,對於col函數,dims及以前的維度(1:dims)被看做列:
- > b <- array(rep(1:3, each=9), dim=c(3,3,3))
- > b
- , , 1
- [,1] [,2] [,3]
- [1,] 1 1 1
- [2,] 1 1 1
- [3,] 1 1 1
- , , 2
- [,1] [,2] [,3]
- [1,] 2 2 2
- [2,] 2 2 2
- [3,] 2 2 2
- , , 3
- [,1] [,2] [,3]
- [1,] 3 3 3
- [2,] 3 3 3
- [3,] 3 3 3
- > rowSums(b)
- [1] 18 18 18
- > rowSums(b,dims=1)
- [1] 18 18 18
- > rowSums(b,dims=2)
- [,1] [,2] [,3]
- [1,] 6 6 6
- [2,] 6 6 6
- [3,] 6 6 6
- > colSums(b)
- [,1] [,2] [,3]
- [1,] 3 6 9
- [2,] 3 6 9
- [3,] 3 6 9
- > colSums(b,dims=2)
- [1] 9 18 27
table可以統計數字出現的頻率,也可以統計其他可以被看做因子的數據類型:
- > table(b)
- b
- 1 2 3
- 9 9 9
- > c <- sample(letters[1:5], 10, replace=TRUE)
- > c
- [1] "a" "c" "b" "d" "a" "e" "d" "e" "c" "a"
- > table(c)
- c
- a b c d e
- 3 1 2 2 2
如果參數不只一個,它們的長度應該一樣,結果是不同因子組合的頻度表:
- > a <- rep(letters[1:3], each=4)
- > b <- sample(LETTERS[1:3],12,replace=T)
- > table(a,b)
- b
- a A B C
- a 0 3 1
- b 3 0 1
- c 1 1 2
二、apply系列函數:
如果我們關心的不僅僅是求和、平均值和頻度這些指標的計算,可以用apply系列函數來處理,這些函數包括apply、lapply、sapply、vapply、tapply和mapply。這些函數的使用可以從目標數據類型和返回值類型兩個方面進行了解。
1、apply函數:
這個函數的使用格式爲:apply(X, MARGIN, FUN, ...)。它應用的數據類型是數組或矩陣,返回值類型由FUN函數結果的長度確定。
X參數爲數組或矩陣;MARGIN爲要應用計算函數的邊/維,MARGIN=1爲第一維(行),2爲第二維(列),...;FUN爲要應用的計算函數,後面可以加FUN的有名參數。比如,要按行或列計算數組a的標準差就可以這樣:
- > apply(a, MARGIN=1, FUN=sd)
- [1] 1 1 1
- > apply(a, MARGIN=2, FUN=sd)
- [1] 0 0 0
MARGIN的長度可以不是1(多維應用),如果長度等於X的維數,應用到FUN函數的數據就只有一個值,結果沒什麼意義,甚至函數會獲得無效值:
- > apply(b, MARGIN=3, FUN=sum)
- [1] 9 18 27
- > apply(b, MARGIN=1:2, FUN=sum)
- [,1] [,2] [,3]
- [1,] 6 6 6
- [2,] 6 6 6
- [3,] 6 6 6
- > apply(a, MARGIN=1:2, FUN=sd)
- [,1] [,2] [,3]
- [1,] NA NA NA
- [2,] NA NA NA
- [3,] NA NA NA
上面我們使用的sd、sum或mean函數的返回值的向量長度都是1(每一次單獨計算),apply函數結果的維數與MARGIN的向量長度相同;如果FUN函數返回值的長度不是1而是每次都爲n,apply函數的結果是維度爲c(n, dim(X)[MARGIN]):
- > a
- [,1] [,2] [,3]
- [1,] 1 2 3
- [2,] 1 2 3
- [3,] 1 2 3
- > apply(a, MARGIN=1, FUN=quantile, probs=seq(0,1, 0.25))
- [,1] [,2] [,3]
- 0% 1.0 1.0 1.0
- 25% 1.5 1.5 1.5
- 50% 2.0 2.0 2.0
- 75% 2.5 2.5 2.5
- 100% 3.0 3.0 3.0
- > apply(a, MARGIN=2, FUN=quantile, probs=seq(0,1, 0.25))
- [,1] [,2] [,3]
- 0% 1 2 3
- 25% 1 2 3
- 50% 1 2 3
- 75% 1 2 3
- 100% 1 2 3
如果FUN函數返回值的長度不一樣,情況就複雜了,apply函數的結果會是列表。
2、lapply、sapply和vapply函數:
這幾個函數是一套,前兩個參數都爲X和FUN,其他參數在R的函數幫助文檔裏有相信介紹。它們應用的數據類型都是列表,對每一個列表元素應用FUN函數,但返回值類型不大一樣。lappy是最基本的原型函數,sapply和vapply都是lapply的改進版。
2.1 lapply返回的結果爲列表,長度與X相同
- > scores <- list(YuWen=c(80,88,94,70), ShuXue=c(99,87,100,68,77))
- > lapply(scores, mean)
- $YuWen
- [1] 83
- $ShuXue
- [1] 86.2
- > lapply(scores, quantile, probs=c(0.5,0.7,0.9))
- $YuWen
- 50% 70% 90%
- 84.0 88.6 92.2
- $ShuXue
- 50% 70% 90%
- 87.0 96.6 99.6
2.2 sapply返回的結果比較“友好”,如果結果很整齊,就會得到向量或矩陣或數組
sapply是simplify了的lapply,所謂的simplify,是指對結果的數據結構進行了simplify,方便後續處理。
- > sapply(scores, mean)
- YuWen ShuXue
- 83.0 86.2
- > sapply(scores, quantile, probs=c(0.5,0.7,0.9))
- YuWen ShuXue
- 50% 84.0 87.0
- 70% 88.6 96.6
- 90% 92.2 99.6
2.3 vapply函數:對返回結果(value)進行類型檢查的sapply
雖然sapply的返回值比lapply好多了,但可預測性還是不好,如果是大規模的數據處理,後續的類型判斷工作會很麻煩而且很費時。vapply增加的FUN.VALUE參數可以直接對返回值類型進行檢查,這樣的好處是不僅運算速度快,而且程序運算更安全(因爲結果可控)。下面代碼的rt.value變量設置返回值長度和類型,如果FUN函數獲得的結果和rt.value設置的不一致(長度和類型)都會出錯:
- > probs <- c(1:3/4)
- > rt.value <- c(0,0,0) #設置返回值爲3個數字
- > vapply(scores, quantile, FUN.VALUE=rt.value, probsprobs=probs)
- YuWen ShuXue
- 25% 77.5 77
- 50% 84.0 87
- 75% 89.5 99
- > probs <- c(1:4/4)
- > vapply(scores, quantile, FUN.VALUE=rt.value, probsprobs=probs)
錯誤於vapply(scores, quantile, FUN.VALUE = rt.value, probs = probs) :
值的長度必需爲3,
但FUN(X[[1]])結果的長度卻是4
- > rt.value <- c(0,0,0,0) #返回值類型爲4個數字
- > vapply(scores, quantile, FUN.VALUE=rt.value, probsprobs=probs)
- YuWen ShuXue
- 25% 77.5 77
- 50% 84.0 87
- 75% 89.5 99
- 100% 94.0 100
- > rt.value <- c(0,0,0,'') #設置返回值爲3個數字和1個字符串
- > vapply(scores, quantile, FUN.VALUE=rt.value, probsprobs=probs)
錯誤於vapply(scores, quantile, FUN.VALUE = rt.value, probs = probs) :
值的種類必需是'character',
但FUN(X[[1]])結果的種類卻是'double'
FUN.VALUE爲必需參數。
3、 mapply函數:
R的在線文檔說mapply是sapply的多變量版本(multivariate sapply),但它的參數順序和sapply卻不一樣:
mapply(FUN, ..., MoreArgs = NULL, SIMPLIFY = TRUE, USE.NAMES = TRUE)
mapply應用的數據類型爲向量或列表,FUN函數對每個數據元素應用FUN函數;如果參數長度爲1,得到的結果和sapply是一樣的;但如果參數長度不是1,FUN函數將按向量順序和循環規則(短向量重複)逐個取參數應用到對應數據元素:
- > sapply(X=1:4, FUN=rep, times=4)
- [,1] [,2] [,3] [,4]
- [1,] 1 2 3 4
- [2,] 1 2 3 4
- [3,] 1 2 3 4
- [4,] 1 2 3 4
- > mapply(rep, x = 1:4, times=4)
- [,1] [,2] [,3] [,4]
- [1,] 1 2 3 4
- [2,] 1 2 3 4
- [3,] 1 2 3 4
- [4,] 1 2 3 4
- > mapply(rep, x = 1:4, times=1:4)
- [[1]]
- [1] 1
- [[2]]
- [1] 2 2
- [[3]]
- [1] 3 3 3
- [[4]]
- [1] 4 4 4 4
- > mapply(rep, x = 1:4, times=1:2)
- [[1]]
- [1] 1
- [[2]]
- [1] 2 2
- [[3]]
- [1] 3
- [[4]]
- [1] 4 4
4、tapply 和 by 函數:
tapply函數可以看做是table函數的擴展:table函數按因子組合計算頻度,而tapply可以按因子組合應用各種函數。使用格式爲:tapply(X, INDEX, FUN = NULL, ..., simplify = TRUE)
X爲要應用函數的數據,通常爲向量;INDEX爲因子,和table函數一樣,它的長度必需和X相同。
- > (x <- 1:10)
- [1] 1 2 3 4 5 6 7 8 9 10
- > (f <- gl(2,5, labels=c("CK", "T")))
- [1] CK CK CK CK CK T T T T T
- Levels: CK T
- > tapply(x, f, length) #FUN函數是length,得到的結果和table類似
- CK T
- 5 5
- > table(f)
- f
- CK T
- 5 5
- > tapply(x, f, sum)
- CK T
- 15 40
by函數是tapply函數針對數據框類型數據的應用,但結果不怎麼友好,你可以用下面語句看看情況:
- with(mtcars, by(mtcars, cyl, summary))
三、aggregate函數
這個函數的功能比較強大,它首先將數據進行分組(按行),然後對每一組數據進行函數統計,最後把結果組合成一個比較nice的表格返回。根據數據對象不同它有三種用法,分別應用於數據框(data.frame)、公式(formula)和時間序列(ts):
- aggregate(x, by, FUN, ..., simplify = TRUE)
- aggregate(formula, data, FUN, ..., subset, nana.action = na.omit)
- aggregate(x, nfrequency = 1, FUN = sum, ndeltat = 1, ts.eps = getOption("ts.eps"), ...)
我們通過 mtcars 數據集的操作對這個函數進行簡單瞭解。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 ...
先用attach函數把mtcars的列變量名稱加入到變量搜索範圍內,然後使用aggregate函數按cyl(汽缸數)進行分類計算平均值:
- > attach(mtcars)
- > aggregate(mtcars, by=list(cyl), FUN=mean)
- Group.1 mpg cyl disp hp drat wt qsec vs am gear carb
- 1 4 26.66364 4 105.1364 82.63636 4.070909 2.285727 19.13727 0.9090909 0.7272727 4.090909 1.545455
- 2 6 19.74286 6 183.3143 122.28571 3.585714 3.117143 17.97714 0.5714286 0.4285714 3.857143 3.428571
- 3 8 15.10000 8 353.1000 209.21429 3.229286 3.999214 16.77214 0.0000000 0.1428571 3.285714 3.500000
by參數也可以包含多個類型的因子,得到的就是每個不同因子組合的統計結果:
- > aggregate(mtcars, by=list(cyl, gear), FUN=mean)
- Group.1 Group.2 mpg cyl disp hp drat wt qsec vs am gear carb
- 1 4 3 21.500 4 120.1000 97.0000 3.700000 2.465000 20.0100 1.0 0.00 3 1.000000
- 2 6 3 19.750 6 241.5000 107.5000 2.920000 3.337500 19.8300 1.0 0.00 3 1.000000
- 3 8 3 15.050 8 357.6167 194.1667 3.120833 4.104083 17.1425 0.0 0.00 3 3.083333
- 4 4 4 26.925 4 102.6250 76.0000 4.110000 2.378125 19.6125 1.0 0.75 4 1.500000
- 5 6 4 19.750 6 163.8000 116.5000 3.910000 3.093750 17.6700 0.5 0.50 4 4.000000
- 6 4 5 28.200 4 107.7000 102.0000 4.100000 1.826500 16.8000 0.5 1.00 5 2.000000
- 7 6 5 19.700 6 145.0000 175.0000 3.620000 2.770000 15.5000 0.0 1.00 5 6.000000
- 8 8 5 15.400 8 326.0000 299.5000 3.880000 3.370000 14.5500 0.0 1.00 5 6.000000
公式(formula)是一種特殊的R數據對象,在aggregate函數中使用公式參數可以對數據框的部分指標進行統計:
- > aggregate(cbind(mpg,hp) ~ cyl+gear, FUN=mean)
- cyl gear mpg hp
- 1 4 3 21.500 97.0000
- 2 6 3 19.750 107.5000
- 3 8 3 15.050 194.1667
- 4 4 4 26.925 76.0000
- 5 6 4 19.750 116.5000
- 6 4 5 28.200 102.0000
- 7 6 5 19.700 175.0000
- 8 8 5 15.400 299.5000
上面的公式 cbind(mpg,hp) ~ cyl+gear 表示使用 cyl 和 gear 的因子組合對 cbind(mpg,hp) 數據進行操作。
aggregate在時間序列數據上的應用請參考R的函數說明文檔。