R 的 plyr 包

在数据分析中,整理数据的本质可以归纳为:对数据进行分割(Split),然后应用(Apply)某些处理函数,最后将结果重新组合(Combine)成所需的格式返回,简单描述为:Split - Apply - Combine。这个过程可以通过Basic包的apply家族函数来实现,apply家族函数包括了apply、sapply、lapply、tapply、aggregate等,可以应用于数据分析的各个阶段。plyr包是apply家族函数的升级,使用plyr包可以实现:在一个函数内同时完成“Split - Apply - Combine”,并且,plyr包实现R类型(vector, list, data.frame)之间的分组变换,基本上可以取代basic包中的apply家族函数。

plyr包对核心函数的命名采用统一的格式:**ply,所有的函数名都由5个字符组成,且最后三个字符是ply,函数名的第一个字符代表输入数据的类型,第二个字符代表输出数据的类型,R类型的简写是:

  • d:data.frame

  • l:list

  • a:array,vector,matrix

  • r:代表replicate

  • _:舍弃输出结果

这种统一的命名格式,使得plyr包的函数更容易记忆和使用,但是,plyr包不是预装于R语言中,使用之前,需要加载和引用plyr包:

install.packages("plyr")library(plyr)

一,使用apply家族函数实现分组聚合

在apply家族函数中,函数有适用的数据类型:

  • apply函数只能用于矩阵,

  • lapply函数能够用于向量和列表(list),其工作原理是把一个函数应用于一个列表中的每个元素上,并且把结果作为列表返回;

  • sapply处理列表,返回向量。

  • mapply函数,把调用的函数应用到多个列表的每一个元素中。

  • tapply函数用于分组聚合运算,在研究数据时,有时需要对数据按照特定的字段进行分组,然后统计各个分组的数据,这就是SQL语法中的分组聚合。

在R语言中,分组聚合可以通过三步实现:拆分-应用-合并(Split-Apply-Combine)。例如,对玩家的游戏成绩进行统计和分析,创建示例数据:

> players_scores <- data.frame(     player=rep(c('Tom','Dick','Jim'),times=c(2,5,3)),     score=round(runif(10,1,100),-1) )

1,分组数据

计算每个玩家的平均得分,首先对玩家分组,需要用到split()函数,按照特定的字段对数据进行分组:

split(x, f, drop = FALSE, ...)

参数注释:

  • x:数据框或向量,是被分组的数据;

  • f:因子类型,按照f对x进行分组;

函数的返回值是一个列表对象,每一个列表项都是包含分组数据的向量。

例如,split(score,player)函数的作用是按照player字段把数据框中的score拆分成一组,也就是说,player 相同的score是同一个分组,填充到同一个列表项中:

> (scores_by_player <- with(players_scores,split(score,player)))$Dick[1] 70 20 30 70 70$Jim[1] 80 90 50$Tom[1] 80 90

2,应用函数

当数据分割之后,对每个分组计算平均分。使用lapply()函数,对于每个列表项,应用mean()函数,计算单个列表项的平均值,例如:

list_mean_by_player <- lapply(scores_by_player,mean)

3,组合数据

组合数据是为了显示数据,在显示最终的数据时,通常把列表转换为向量。lapply()函数返回的结果是一个列表对象,每一个列表项都是一个向量,因此可以使用unlist()函数,把列表转换为向量,例如:

> unlist(list_mean_by_player)    Dick      Jim      Tom 52.00000 73.33333 85.00000

二,使用plyr包实现分组聚合

在数据分析中,使用Basic包实现”拆分-应用-合并“ 显得十分繁琐,可以使用tapply()函数一次完成所有的三个步骤,一气呵成:

with(players_scores,tapply(score,player,mean))

tapply()函数常用的参数共有三个,第一个参数是:数据框对象或向量,第二个参数是因子列表,也就是分组字段,第三个参数是指对单个分组应用的函数变量:

tapply(X, INDEX, FUN = NULL, ...)

by()函数和aggregate()函数是tapply()函数的包装函数,功能相同,接口稍微不同。

by(data, INDICES, FUN, ..., simplify = TRUE)aggregate(x, by, FUN, ..., simplify = TRUE, drop = TRUE)

三,plyr包的核心函数

plyr包中最常用的函数是ddply()函数,该函数对数据框进行操作,对每一行调用一个函数,并返回数据框类型:

ddply(.data, .variables, .fun = NULL, ...)

参数注释:

  • .data:函数处理的数据框;

  • .variables:要进行拆分的变量名称,传递变量的格式是: .(col_name),就是把进行分组的变量名包含在.()中;

  • .fun:应用到每行的函数

  • ...:传递到fun的其他参数

对于参数fun,有两种赋值方式:

1. 如果使用colwise函数,那么这使ddply函数把参数fun应用于每一列,除了参数variable指定的数据列之外,例如:

ddply(diamonds,.(color),colwise(mean))

2. 使用summarize函数对指定的列执行操作,更为灵活,例如:

> ddply(diamonds,.(color),summarize,avg_price=mean(price),avg_carat=mean(carat))  color avg_price avg_carat1     D  3169.954 0.65779482     E  3076.752 0.6578667
.....

四,each函数

plyr包的each()函数,能够把多个函数整合到一个函数中,每一个函数必须只能返回一个数值:

each(...)

使用each()函数,可以使函数aggregate()同时调用多个函数:

> aggregate(cbind(price,carat)~cut+color,diamonds,each(mean,sum))         cut color  
posted @ 2019-01-13 22:21  赏尔  阅读(422)  评论(0编辑  收藏  举报