昨天看到豆瓣上一篇文章,是作者關于讀Hadley Wickham的文章The Split-Apply-Combine Strategy for Data Analysis的筆記。
文章位址
自己在用R整理資料的時候,為了避免顯示循環,使用apply函數族的時候,常常遇到輸入類型和輸出類型搞混的情況,這篇文章對R base中的 split-apply-combine有一個很好的整理。以及介紹了R社群中資料整理大牛Wickham的一個R包-plyr。
plyr包是Hadley Wickham為解決split – apply – combine問題而寫的一個包,其動機在與提供超越for循環和内置的apply函數族的一個一攬子解決方案。使用plyr包可以針對不同的資料類型,在一個函數内同時完成split – apply – combine三個步驟,以實作最大限度的高效和簡潔。
plyr包特别适合處理大型資料集問題,比如對空間資料的空間位置或時間序列面闆資料的時間點模組化,或者在高維數組中進行資料探索等等。
資料轉換常用的一個模式:split-apply-combine。具體的說就是:将一個大資料分拆成小塊,在每一個小塊内進行操作,合并操作結果。
split
函數split()可以按照分組因子,把向量,矩陣和資料框進行适當的分組。它的傳回值是一個清單,代表分組變量每個水準的觀測。這個清單可以使用sapply(),lappy()進行處理(apply – combine步驟),得到問題的最終結果。
split(x,f)其中x是待分組的向量、矩陣、資料框,f是分組因子,傳回值是一個清單。
- Example1:對向量分組
n <- 10
nn <- 100
g <- factor(round(n * runif(n * nn))) #runif産生均勻分布,預設參數是0-1之間的。
x <- rnorm(n * nn) + sqrt(as.numeric(g))
xg <- split(x, g)
str(xg)
List of
$ : num [:] ...
$ : num [:] - ...
$ : num [:] ...
$ : num [:] ...
$ : num [:] ...
$ : num [:] ...
$ : num [:] ...
$ : num [:] ...
$ : num [:] ...
$ : num [:] ...
$ : num [:] ...
可以看出傳回值是一個清單。
- Example2:對矩陣分組
a <- matrix(c(:, rep(:, )), ncol = ) #産生一個三列的矩陣
a
[,] [,] [,]
[,]
[,]
[,]
[,]
[,]
[,]
[,]
[,]
[,]
[,]
b <- split(a, col(a)) # 案列分組
b
$`1`
[]
$`2`
[]
$`3`
[]
c <- split(a[, -], factor(a[, ])) #按照第三列分組
c
$`1`
[]
$`2`
[]
- Example3:對資料框分組
a <- data.frame(a = :, b = :, c = rep(:, each = )) #産生一個三列的資料框
a
a b c
b <- split(a, a$c) #按照第三列分組
b
$`1`
a b c
$`2`
a b c
unsplit()函數是split()函數的逆函數,可以使分組和好如初。
subset()取子集的一個函數
'data.frame': obs. of variables:
$ Ozone : int NA NA ...
$ Solar.R: int NA NA ...
$ Wind : num ...
$ Temp : int ...
$ Month : int ...
$ Day : int ...
Ozone Temp
NA
NA
NA
cut()劃分數值變量的取值
strsplit()分割字元變量
apply函數族
aplly函數族主要用來完成apply-combine過程,該函數族的使用經常讓我混亂。
apply :Apply Functions Over Array Margins
by :Apply a Function to a Data Frame Split by Factors
eapply :Apply a Function Over Values in an Environment
lapply :Apply a Function over a List or Vector
mapply :Apply a Function to Multiple List or Vector Arguments
rapply :Recursively Apply a Function to a List
tapply :Apply a Function Over a Ragged Array
除此之外,還有可作為lapply變形的sapply,vapply和 replicate,共計10個函數。
apply()函數作用于數組、矩陣、資料框,對行或者列作用,傳回一個向量、數組或者清單
by函數矩陣或者資料框,作用于按行分組的子集,傳回一個清單或者數組。它是tapply的友好版
lapply作用于清單或者向量使用函數,傳回一個清單
sapply是lapply的使用者友好版,如何合适的話,可以傳回一個向量或者矩陣
vapply類似sapply,可以預先定義傳回值的類型
i39 <- sapply(:, seq) # list of vectors
sapply(i39, fivenum)
## [,1] [,2] [,3] [,4] [,5] [,6] [,7]
## [1,] 1.0 1.0 1 1.0 1.0 1.0 1
## [2,] 1.5 1.5 2 2.0 2.5 2.5 3
## [3,] 2.0 2.5 3 3.5 4.0 4.5 5
## [4,] 2.5 3.5 4 5.0 5.5 6.5 7
## [5,] 3.0 4.0 5 6.0 7.0 8.0 9
vapply(i39, fivenum, c(Min. = , `1st Qu.` = , Median = , `3rd Qu.` = , Max. = ))
## [,1] [,2] [,3] [,4] [,5] [,6] [,7]
## Min. 1.0 1.0 1 1.0 1.0 1.0 1
## 1st Qu. 1.5 1.5 2 2.0 2.5 2.5 3
## Median 2.0 2.5 3 3.5 4.0 4.5 5
## 3rd Qu. 2.5 3.5 4 5.0 5.5 6.5 7
## Max. 3.0 4.0 5 6.0 7.0 8.0 9
mapply()作用于多重清單或者是向量參數
## [[1]]
## []
##
## [[2]]
## []
##
## [[3]]
## []
##
## [[4]]
## []
## [[1]]
## []
##
## [[2]]
## []
##
## [[3]]
## []
##
## [[4]]
## []
## [[1]]
## []
##
## [[2]]
## []
##
## [[3]]
## []
##
## [[4]]
## []
mapply(function(x, y) seq_len(x) + y,
c(a = 1, b = 2, c = 3), # names from first
c(A = 10, B = 0, C = -10))
## $a
## [1] 11
##
## $b
## [1] 1 2
##
## $c
## [1] -9 -8 -7
word <- function(C, k) paste(rep.int(C, k), collapse = "")
utils::str(mapply(word, LETTERS[:], :, SIMPLIFY = FALSE))
## List of 6
## $ A: chr "AAAAAA"
## $ B: chr "BBBBB"
## $ C: chr "CCCC"
## $ D: chr "DDD"
## $ E: chr "EE"
## $ F: chr "F"
rapply()遞歸的應用一個函數到清單 (可以認為是作用于清單中的每一個元素?)
X <- list(list(a = pi, b = list(c = :)), d = "a test")
X
## [[1]]
## [[1]]$a
## []
##
## [[1]]$b
## [[1]]$b$c
## []
##
##
##
## $d
## [] "a test"
rapply(X, function(x) x, how = "replace")
## [[1]]
## [[1]]$a
## []
##
## [[1]]$b
## [[1]]$b$c
## []
##
##
##
## $d
## [] "a test"
## [[1]]
## [[1]]$a
## []
##
## [[1]]$b
## [[1]]$b$c
## []
##
##
##
## $d
## [] "a test"
rapply(X, nchar, classes = "character", deflt = as.integer(NA), how = "list")
## [[1]]
## [[1]]$a
## [] NA
##
## [[1]]$b
## [[1]]$b$c
## [] NA
##
##
##
## $d
## []
rapply(X, nchar, classes = "character", deflt = as.integer(NA), how = "unlist")
## a b.c d
## NA NA 6
## d
## 6
## [[1]]
## [[1]]$a
## []
##
## [[1]]$b
## [[1]]$b$c
## []
##
##
##
## $d
## [] "a test"
tapply()對不規則的數組按确定的因子計算函數
## breaks wool tension
## 1 26 A L
## 2 30 A L
## 3 54 A L
## 4 25 A L
## 5 70 A L
## 6 52 A L
tapply(warpbreaks$breaks, warpbreaks[, -], sum)
## tension
## wool L M H
## A 401 216 221
## B 254 259 169
plyr包
plyr包函數的命名規則 | array | data.frame | list | nothing |
---|---|---|---|---|
array | aaply | adply | alply | a_ply |
data.frame | daply | ddply | dlply | d_ply |
list | laply | ldply | llply | l_ply |
n replicates | raply | rdply | rlply | r_ply |
function arguments | maply | mdply | mlply | m_ply |