前情回顾:apply函数族理解与运用
上篇博客我们提到了apply函数族的基本使用方法,但各函数之间缺乏规律性,时间一长很容易忘记相关用法。鉴此,今天介绍的plyr
程序扩展包能很好的解决该问题。
plyr
扩展包操作数据的主要思想为【分割—应用—组合】,即将一个问题分割成各个小部分,再对每个小部分进行独立操作,最后将各部分的操作组合起来,这与
MapReduce
的思想不谋而合呀!
一、主要函数介绍
plyr扩展包涉及的主要函数可以用**ply
来概括,第一个*
表示输入数据的结构,可选的数据结构包括a(array)
、d(data.frame)
和l(list)
;第二个*
表示输出数据的结构,可选的数据结构除前面三种以外,还有_
表示不输出,它的结果常用于绘图和建立缓存。根据输入和输出的划分,可将plyr
扩展包划分为12个主要函数,如下表所示。
输入 | 输出数组 | 输出数据框 | 输出列表 | 无输出 |
---|---|---|---|---|
数组 | aaply | adply | alply | a_ply |
数据框 | daply | ddply | dlply | d_ply |
列表 | daply | ldply | llply | l_ply |
对于**ply()
函数来说,按照其输入数据的结构可划分为三类:a*ply()
、d*ply()
、l*ply()
,三类的参数如下
a * ply(.data,.margins,.fun,…,.progress=“none”)
d * ply(.data,variables,.fun,…,.progress=“none”)
l * ply(.data,.fun,…,.progress=“none”)
以上三类函数的切割方式不尽相同,具体表现为:
a*ply()
函数按照维度对数组进行切片d*ply()
函数按照一列或多列将数据框分为若干子集l*ply()
函数将列表的每个分量作为子集
其中,.data
表示输入数据;.margins
表示数组的边际,与apply
的margin
参数类似,也可为向量;variables
表示分组变量,可以有多组变量;.fun
表示应用于数据各个部分的函数,如果没有指定的.fun
,则表示从一种数据结构转变为另一种数据结构;...
表示传递给.fun
的其他参数;.progress
表示进度条类型,共text
、tk
、win
三种可选,none
表示不显示进度条
二、示例演示
2.1 不设置.fun参数
以鸢尾花数据为例,现不指定.fun
参数,观察变化前后数据的结构
library(plyr)
iris_species<-dlply(iris,.variables="Species")
str(iris)
str(iris_species)
从结果可知,**ply()函数
,若不在.fun
中指定应用函数,它的作用仅是将转变数据集的结构。
2.2 鸢尾花不同种类回归
现继续以鸢尾花数据集为例,对每个鸢尾花种类,进行花瓣长度与宽度回归,观察不同种类下的回归系数有何差异。
#dlply方式求解
linear_model1<-function(df){
lm(Petal.Length~Petal.Width+1,data=df)
}
iris_lm<-dlply(iris,.variables="Species",.fun=linear_model1,.progress="text")
iris_lm
#alply方式求解
linear_model2<-function(df){
lm(`Petal L.`~`Petal W.`+1,data=as.data.frame(df))
}
iris3_lm<-alply(iris3,.margins = 3,.fun=linear_model2)
iris3_lm


注意:以上两个函数本质相同,都是对鸢尾花的不同种类进行花瓣长度与宽度的回归,回归结果也证实了这一点。差别在于数据集对象的差异,如列名不一致。且内置iris3
数据集为一个三维数组,故在回归时需要将其转为数据框,并设置.margin
参数为3
2.3 重写持续降雨日逻辑
在上篇博客中,我们曾用sapply
函数和tapply
函数计算了每个站点的最长持续降雨日。当然,我们也可以用d*ply()
函数实现它。
library(plyr)
data<-read.table("rainfall.txt",header=T)
duration_caculate_dd<-function(x){
zero_rainfall_loc<-which(x["rainfall"]==0)
rainfall_vec<-c()
last_loc<-length(zero_rainfall_loc)-1
if(last_loc>=1){
for(i in 1:last_loc){
duration<-x[zero_rainfall_loc[i]:zero_rainfall_loc[i+1],"rainfall"]
rainfall_duration<-length(which(duration!=0))
rainfall_vec<-c(rainfall_vec,rainfall_duration)
}
max_rainfall_duration<-max(rainfall_vec)
return(max_rainfall_duration)
} else{
max_rainfall_duration<-0
return(max_rainfall_duration)
}
}
dd_rst<-ddply(data,.variables="loc_id",duration_caculate_sa)
head(dd_rst)
从输出结果来看,与上篇博客的结果对比,ddply
函数输出的结果仅是将loc_id
从行索引中拿出来,单独作为一列,给人更加工整的感觉。
以上就是本次分享的全部内容~