失眠网,内容丰富有趣,生活中的好帮手!
失眠网 > purrr | 使用map族函数进行向量化运算

purrr | 使用map族函数进行向量化运算

时间:2023-07-07 14:27:57

相关推荐

purrr | 使用map族函数进行向量化运算

前面介绍的进行向量化运算的apply族函数来自基础包base,而本文介绍的map族函数则来自purrr包,是tidyverse家族的一员。与apply相比,map函数在逻辑上更易于理解,并且支持匿名函数和格式化输出结果。

1 map()函数

map()函数相当于base中的apply()函数,适用于单参数向量化运算,语法结构如下:

map(.x,.f,...)

map()函数的语法结构比较简单,.x是以某种结构储存的多组数据,.f是应用于.x中每组数据的的函数,...为该函数的其他参数;

map()自带的参数名称带有前缀.,可以和继承自.f中的参数名相区别;

.x适用结构为向量或list,以及其他可强制转化为这两种结构的其他数据结构。

比如,使用正态随机数生成函数rnorm()生成多组随机数,rnorm()的语法结构:

rnorm(n,mean=0,sd=1)

均值mean和方差sd固定,数目分别为3、5和7

library(purrr)#均值和方差取默认值map(c(3,5,7),rnorm)#自定义均值和方差map(c(3,5,7),rnorm,mean=10,sd=5)

#部分输出结果#均值和方差取默认值map(c(3,5,7),rnorm)##[[1]]##[1]-1.0388121.0272072.454847####[[2]]##[1]-0.6810901-0.44813081.82731131.41771810.8114058####[[3]]##[1]-2.1307517-0.82967051.7878942-0.5691242-0.70111140.84571540.6703464#自定义均值和方差map(c(3,5,7),rnorm,mean=10,sd=5)##[[1]]##[1]13.1450711.7480410.49418####[[2]]##[1]12.64045915.38736210.4674029.82542915.142579####[[3]]##[1]7.72944316.3719329.7905157.92236611.20765815.41454117.237151

随机数数目和方差固定,均值分别为3、5和7(即以第二个参数为向量化运算依据)

map(c(3,5,7),rnorm,n=5,sd=1)

#输出结果map(c(3,5,7),rnorm,n=5,sd=1)##[[1]]##[1]3.2595742.4553162.9952613.6722392.100866####[[2]]##[1]4.8364674.9882174.1051245.1064235.618277####[[3]]##[1]7.4839866.8905077.0414647.3483076.810796

apply()不同的是,map()中没有MARGIN参数,即指定运算的维度,因为.x的标准结构为向量或list,而二者本身就都只有一个维度。像矩阵、数据框这样的多维数据结构,放在.x位置上函数会将其强制转换为list再进行计算。比较下面两句代码输出结果长度的区别:

map(mtcars,mean,na.rm=T)%>%length()map(as.matrix(mtcars),mean,na.rm=T)%>%length()

#输出结果map(mtcars,mean,na.rm=T)%>%length()##[1]11map(as.matrix(mtcars),mean,na.rm=T)%>%length()##[1]352

数据框转化为list,会将每列作为list的一个元素,因此是个长度为11的list;

矩阵转换为list,它的每个元素都会被当作list的一个元素,因此是长度为352的list。

2 map2()函数

map2()函数适用于两个参数的向量化运算,语法结构如下:

map2(.x,.y,.f,...)

比如分别以8、9、10为均值,1、2、3为方差,生成5个符合正态分布的随机数:

map2(.x=c(8:10),.y=c(1:3),rnorm,n=5)

#部分输出结果map2(.x=c(8:10),.y=c(1:3),rnorm,n=5)##[[1]]##[1]8.1108948.8657968.6958776.61614210.102844####[[2]]##[1]8.5918969.7590567.7116708.6136856.816343####[[3]]##[1]9.2702387.9828705.7061085.2892538.178568

3 imap()函数

imap()函数是map2()函数的特殊形式。它不需要.y参数,而是自动将.x参数中的数据的行名(无行名时使用行序号)作为.y参数。语法结构如下:

imap(.x,.y,.f,...)

x<-y<-c(1:5)names(x)<-LETTERS[1:5]imap(x,paste,sep="-")imap(y,paste,sep="-")

#部分输出结果imap(x,paste,sep="-")##$A##[1]"1-A"####$B##[1]"2-B"####$C##[1]"3-C"####$D##[1]"4-D"####$E##[1]"5-E"imap(y,paste,sep="-")##[[1]]##[1]"1-1"####[[2]]##[1]"2-2"####[[3]]##[1]"3-3"####[[4]]##[1]"4-4"####[[5]]##[1]"5-5"

4 pmap()函数

pmap()函数适用于多参数的向量化运算,语法结构如下:

pmap(.l,.f,...)

.l是list或数据框结构,它的每个元素或每列代表一个参数。如下:

pmap(list(n=c(5:7),mean=c(8:10),sd=c(1:3)),rnorm)pmap(data.frame(n=c(5:7),mean=c(8:10),sd=c(1:3)),rnorm)

#输出结果pmap(list(n=c(5:7),mean=c(8:10),sd=c(1:3)),rnorm)##[[1]]##[1]6.6564748.5390448.4780017.899.822755####[[2]]##[1]10.5598838.85118211.14722810.3853348.00372312.515218####[[3]]##[1]12.45552117.2562388.90354212.27036310.4575548.9222549.615747pmap(data.frame(n=c(5:7),mean=c(8:10),sd=c(1:3)),rnorm)##[[1]]##[1]9.26011310.1881327.4312128.3083988.629498####[[2]]##[1]7.9877547.43800810.9943677.5192158.0443078.215979####[[3]]##[1]14.0616438.7221189.08056813.2303906.5694618.30488610.003861

数据框必须有列名且列名和函数参数名必须相同,每列位置不需要和函数参数位置相同。如下:

pmap(data.frame(mean=c(8:10),n=c(5:7),sd=c(1:3)),rnorm)

#输出结果pmap(data.frame(mean=c(8:10),n=c(5:7),sd=c(1:3)),rnorm)##[[1]]##[1]7.8965897.7054199.3899386.6543327.556056####[[2]]##[1]11.1549459.82962513.8700227.3626139.63034710.574812####[[3]]##[1]11.00222212.79069513.44893411.7037288.7908288.2139188.907189

list的元素可以不命名,没名称的元素按函数的参数顺序依次赋值。如下:

pmap(list(c(8:10),c(5:7),c(1:3)),rnorm)

#输出结果pmap(list(c(8:10),c(5:7),c(1:3)),rnorm)##[[1]]##[1]6.3421206.5304796.6525064.7390465.1351082.7402614.9816877.295926####[[2]]##[1]2.9340937.1535628.444.5301866.7841436.5206723.5205756.232855##[9]9.400873####[[3]]##[1]6.2333608.8555872.0068807.1499948.2767199.0146928.386454##[8]6.1544873.21812910.840443

5 匿名函数

map()族函数调用自定义函数时,可以使用~代替函数function。具体地,

一元函数

map(1:10,~.x+2)#等价于map(1:10,function(x)x+2)

二元函数

map2(1:10,11:2,~.x^(.y))#等价于map2(1:10,11:2,function(x,y)x^y)

多元函数

pmap(list(c(1:10),c(2:11),c(3:12)),~..1^2+..2^3+..3^4)#等价于pmap(list(c(1:10),c(2:11),c(3:12)),function(x,y,z)x^2+y^3+z^4)

更多元函数的参数依次使用..4..5...等代替;

匿名函数的参数名必须带前缀.且严格按照x、y和1、2、3...的顺序使用。

6 格式化输出结果

map族函数默认输出结果的数据结构是list。以map()函数为例,它还有其他几种形式:

map_lgl()map_int()map_dbl()map_chr()函数将输出结果的变量分别转化为逻辑型、整型、双精度性和字符型格式;

map_df()map_dfr()map_dfc()函数将输出结果转为数据框结构,后两者分别按行和列将结果合并。

map_lgl(.x,.f,...)map_chr(.x,.f,...)map_int(.x,.f,...)map_dbl(.x,.f,...)map_dfr(.x,.f,...,.id=NULL)map_dfc(.x,.f,...)

map_dfc(1:10,rnorm,n=10,sd=2)

#输出结果map_dfc(1:10,rnorm,n=10,sd=2)##Newnames:##*NA->...1##*NA->...2##*NA->...3##*NA->...4##*NA->...5##*...###Atibble:10x10##...1...2...3...4...5...6...7...8...9...10##<dbl><dbl><dbl><dbl><dbl><dbl><dbl><dbl><dbl><dbl>##10.5203.305.676.505.396.9911.07.428.689.70##2-1.083.893.754.674.657.374.586.626.598.98##32.501.46-0.06603.165.436.088.2812.19.0612.0##42.712.162.955.745.371.114.592.599.7412.8##50.8923.753.532.066.2510.98.516.6311.86.73##6-2.762.551.354.313.567.405.868.1411.78.26##7-0.9552.131.523.859.013.4510.214.212.09.84##81.182.593.512.625.083.237.148.157.889.59##91.692.072.403.316.006.964.414.6812.411.2##10-2.04-0.3717.414.584.564.574.428.128.8610.8

最后附上一张函数功能示意图:

图片来源于网络:/weixin_38008864/article/details/107572648

如果觉得《purrr | 使用map族函数进行向量化运算》对你有帮助,请点赞、收藏,并留下你的观点哦!

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。