R_Split-Apply-combine
来源:互联网 发布:麦当劳 金拱门 知乎 编辑:程序博客网 时间:2024/05/18 01:34
昨天看到豆瓣上一篇文章,是作者关于读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 <- 10nn <- 100g <- 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 11$ 0 : num [1:50] 1.858 1.999 0.503 2.771 1.624 ...$ 1 : num [1:108] 1.836 1.428 1.432 -0.332 2.857 ...$ 2 : num [1:100] 0.162 2.657 0.151 0.212 1.906 ...$ 3 : num [1:103] 1.16 1.78 3.24 1.9 1.18 ...$ 4 : num [1:104] 3.46 2.58 2.5 3.36 1.97 ...$ 5 : num [1:87] 2.99 2.21 3.39 2.47 2.37 ...$ 6 : num [1:107] 2.88 1.79 1.85 4.14 3.48 ...$ 7 : num [1:82] 4.32 3.34 2.62 2.01 4.02 ...$ 8 : num [1:93] 1.67 5.11 2.8 1.83 2.52 ...$ 9 : num [1:123] 3.6 4.72 2.08 2.32 1.78 ...$ 10: num [1:43] 4.14 1.29 4.14 3.29 3.55 ...
可以看出返回值是一个列表。
- Example2:对矩阵分组
a <- matrix(c(1:20, rep(1:2, 5)), ncol = 3) #产生一个三列的矩阵a
[,1] [,2] [,3] [1,] 1 11 1 [2,] 2 12 2 [3,] 3 13 1 [4,] 4 14 2 [5,] 5 15 1 [6,] 6 16 2 [7,] 7 17 1 [8,] 8 18 2 [9,] 9 19 1[10,] 10 20 2
b <- split(a, col(a)) # 案列分组b
$`1` [1] 1 2 3 4 5 6 7 8 9 10$`2` [1] 11 12 13 14 15 16 17 18 19 20$`3` [1] 1 2 1 2 1 2 1 2 1 2
c <- split(a[, -3], factor(a[, 3])) #按照第三列分组c
$`1` [1] 1 3 5 7 9 11 13 15 17 19$`2` [1] 2 4 6 8 10 12 14 16 18 20
- Example3:对数据框分组
a <- data.frame(a = 1:10, b = 11:20, c = rep(1:2, each = 5)) #产生一个三列的数据框a
a b c1 1 11 12 2 12 13 3 13 14 4 14 15 5 15 16 6 16 27 7 17 28 8 18 29 9 19 210 10 20 2
b <- split(a, a$c) #按照第三列分组b
$`1` a b c1 1 11 12 2 12 13 3 13 14 4 14 15 5 15 1$`2` a b c6 6 16 27 7 17 28 8 18 29 9 19 210 10 20 2
unsplit()函数是split()函数的逆函数,可以使分组和好如初。
subset()取子集的一个函数
str(airquality)
'data.frame': 153 obs. of 6 variables: $ Ozone : int 41 36 12 18 NA 28 23 19 8 NA ... $ Solar.R: int 190 118 149 313 NA NA 299 99 19 194 ... $ Wind : num 7.4 8 12.6 11.5 14.3 14.9 8.6 13.8 20.1 8.6 ... $ Temp : int 67 72 74 62 56 66 65 59 61 69 ... $ Month : int 5 5 5 5 5 5 5 5 5 5 ... $ Day : int 1 2 3 4 5 6 7 8 9 10 ...
head(subset(airquality, Temp > 80, select = c(Ozone, Temp)))
Ozone Temp29 45 8135 NA 8436 NA 8538 29 8239 NA 8740 71 90
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(3:9, seq) # list of vectorssapply(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. = 0, `1st Qu.` = 0, Median = 0, `3rd Qu.` = 0, Max. = 0))
## [,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()作用于多重列表或者是向量参数
mapply(rep, 1:4, 4:1)
## [[1]]## [1] 1 1 1 1## ## [[2]]## [1] 2 2 2## ## [[3]]## [1] 3 3## ## [[4]]## [1] 4
mapply(rep, times = 1:4, x = 4:1)
## [[1]]## [1] 4## ## [[2]]## [1] 3 3## ## [[3]]## [1] 2 2 2## ## [[4]]## [1] 1 1 1 1
mapply(rep, times = 1:4, MoreArgs = list(x = 42))
## [[1]]## [1] 42## ## [[2]]## [1] 42 42## ## [[3]]## [1] 42 42 42## ## [[4]]## [1] 42 42 42 42
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[1:6], 6:1, 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 = 1:1)), d = "a test")X
## [[1]]## [[1]]$a## [1] 3.142## ## [[1]]$b## [[1]]$b$c## [1] 1## ## ## ## $d## [1] "a test"
rapply(X, function(x) x, how = "replace")
## [[1]]## [[1]]$a## [1] 3.142## ## [[1]]$b## [[1]]$b$c## [1] 1## ## ## ## $d## [1] "a test"
rapply(X, sqrt, classes = "numeric", how = "replace")
## [[1]]## [[1]]$a## [1] 1.772## ## [[1]]$b## [[1]]$b$c## [1] 1## ## ## ## $d## [1] "a test"
rapply(X, nchar, classes = "character", deflt = as.integer(NA), how = "list")
## [[1]]## [[1]]$a## [1] NA## ## [[1]]$b## [[1]]$b$c## [1] NA## ## ## ## $d## [1] 6
rapply(X, nchar, classes = "character", deflt = as.integer(NA), how = "unlist")
## a b.c d ## NA NA 6
rapply(X, nchar, classes = "character", how = "unlist")
## d ## 6
rapply(X, log, classes = "numeric", how = "replace", base = 2)
## [[1]]## [[1]]$a## [1] 1.651## ## [[1]]$b## [[1]]$b$c## [1] 1## ## ## ## $d## [1] "a test"
tapply()对不规则的数组按确定的因子计算函数
head(warpbreaks)
## 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[, -1], sum)
## tension## wool L M H## A 401 216 221## B 254 259 169
plyr包
- R_Split-Apply-combine
- combine
- R语言的数据转换: split – apply – combine 模式
- R数据分析当中的化整为零(Split-Apply-Combine)策略
- R语言︱数据集分组、筛选(plit – apply – combine模式、dplyr、data.table)
- apply( )
- apply()
- Path.Combine
- Combine algorithm
- mapreduce combine
- Delegate.Combine
- combine题解
- Combine String
- Path.Combine 的使用
- C#_delegate - combine function
- hadoop combine 使用场景
- Leetcode-Combine Sum II
- Leetcode Combine Sum
- android沉浸式状态栏的实现
- ArcGIS教程:流向
- WEB程序需要打印格式页面时解决方案汇总 .
- Android开发亲测error
- UltraEdit的配置
- R_Split-Apply-combine
- 使用Sonatype Nexus搭建Maven私服后如何添加第三方JAR包?
- Echarts异步模块定义(AMD规范)——require.js
- JS设计模式——观察者模式
- ORA-28002: 密码将在 7 天后到期
- 编写更好的jQuery代码的建议
- Javascript模块化编程(一):模块的写法
- 小心split()函数
- 图像识别练习(字符验证码、车牌号、身份证号)