昨天看到豆瓣上一篇文章,是作者关于读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 |