R语言小白学习笔记8—数据迭代
笔记链接
学习笔记1—R语言基础.
学习笔记2—高级数据结构.
学习笔记3—R语言读取数据.
学习笔记4—统计图.
学习笔记5—编写R语言函数和简单的控制循环语句.
学习笔记6—分组操作.
学习笔记7—高效的分组操作:dplyr.
学习笔记8—数据迭代
虽然R语言有很多方法迭代一个列表或者向量,但purrr包优化和标准化了数据迭代的方法。
8.1 map函数
purrr包的基础是map函数。
map函数将一个函数应用到列表的每个元素,并返回相同长度的一个列表。
map函数被设计来用管道操作。
例:
> library(purrr)
> theList <- list(A=matrix(1:9, 3), B=1:5, C=matrix(1:4, 2), D=2)
> theList %>% map(sum)
$A
[1] 45
$B
[1] 15
$C
[1] 10
$D
[1] 2
当有NA值时,结果会NA:
> theList2 <- theList
> theList2[[1]][2, 1] <- NA
> theList2[[2]][4] <- NA
> theList2 %>% map(sum)
$A
[1] NA
$B
[1] NA
$C
[1] 10
$D
[1] 2
两种解决方法:
1、用封装sum函数的匿名函数
> theList2 %>% map(function(x) sum(x, na.rm=TRUE))
$A
[1] 43
$B
[1] 11
$C
[1] 10
$D
[1] 2
2、为sum函数传入额外参数
> theList2 %>% map(sum, na.rm=TRUE)
$A
[1] 43
$B
[1] 11
$C
[1] 10
$D
[1] 2
编写匿名函数看似麻烦,但它在函数式编程中经常遇到,对使用map函数且无法按序传递函数参数时非常有用。
8.2 特定类型的map函数
map函数返回结果是列表,当需要其他返回结果时可以用map_*形式的函数,*指返回类型。
*注意:map_形式的函数为每个元素输出长度为1的一个向量,当每个元素的返回结果长度大于1时会报错。
1、map_int函数
返回结果必须是整数型
例:用map_int函数将NROW函数应用于每个元素
> theList %>% map_int(NROW)
A B C D
3 5 2 1
2、map_dbl函数
应用于返回结果是数值型的函数
> theList %>% map_dbl(mean)
A B C D
5.0 3.0 2.5 2.0
3、map_chr函数
应用于返回结果是字符型的函数
> theList3 <- list(A=1:5, B=2, C=1:10)
> theList3 %>% map_chr(class)
A B C
"integer" "numeric" "integer"
注意:返回结果必须是长度为1的向量,否则会报错
如:
> theList %>% map_chr(class)
错误: Result 1 must be a single string, not a character vector of length 2
Run `rlang::last_error()` to see where the error occurred.
查看数据类型可以看见返回结果长度大于1:
> theList %>% map(class)
$A
[1] "matrix" "array"
$B
[1] "integer"
$C
[1] "matrix" "array"
$D
[1] "numeric"
4、map_lgl函数
应用于逻辑操作,返回一个逻辑向量
> theList %>% map_lgl(function(x)NROW(x)<3)
A B C D
FALSE FALSE TRUE TRUE
5、map_df函数
输入列表对其迭代应用某个函数来组合返回一个数据框。
> buildDF <- function(x)
+ {
+ data.frame(A=1:x, B=x:1)
+ }
> listOfLengths <- list(3, 4, 1, 5)
> listOfLengths %>% map_df(buildDF)
A B
1 1 3
2 2 2
3 3 1
4 1 4
5 2 3
6 3 2
7 4 1
8 1 1
9 1 5
10 2 4
11 3 3
12 4 2
13 5 1
6、map_if函数
map_if函数:只有满足条件的元素才会被修改,剩下元素不变
例:theList的矩阵元素乘以2
> theList %>% map_if(is.matrix, function(x)x*2)
$A
[,1] [,2] [,3]
[1,] 2 8 14
[2,] 4 10 16
[3,] 6 12 18
$B
[1] 1 2 3 4 5
$C
[,1] [,2]
[1,] 2 6
[2,] 4 8
$D
[1] 2
8.3 数据框的迭代
因为数据框从技术上来讲是列表,所以迭代很简单
例:计算diamonds数据集数值型的列的平均值
> data(diamonds, package = 'ggplot2')
> diamonds %>% map_dbl(mean)
carat cut color clarity
0.7979397 NA NA NA
depth table price x
61.7494049 57.4571839 3932.7997219 5.7311572
y z
5.7345260 3.5387338
可以看到,数值型列返回平均值,非数值型返回NA。
8.4 map函数的多输入
对于只有两个输入参数的情况,推荐使用map2函数,两个以上用pmap函数
> firstList <- list(A=matrix(1:16, 4), B=matrix(1:16, 2),C=1:5)
> secondList <- list(A=matrix(1:16, 4), B=matrix(1:16, 8), C=15:1)
> simpleFunc <- function(x, y)
+ {
+ NROW(x) + NROW(y)
+ }
> map2(firstList, secondList, simpleFunc)
$A
[1] 8
$B
[1] 10
$C
[1] 20
对于更一般的pmap函数,要求将所有列表放进一个列表
> pmap(list(firstList, secondList), simpleFunc)
$A
[1] 8
$B
[1] 10
$C
[1] 20