R语言数据转换——plyr包

时间:2022-09-07 11:57:04
  • plyr包简介

plyr包是Hadley Wickham为解决split – apply – combine问题而写的一个包,其动机在与提供超越for循环和内置的apply函数族的一个一揽子解决方案。使用plyr包可以针对不同的数据类型,在一个函数内同时完成split – apply – combine三个步骤,以实现最大限度的高效和简洁。
plyr包特别适合处理大型数据集问题,比如对空间数据的空间位置或时间序列面板数据的时间点建模,或者在高维数组中进行数据探索等等。

此包作者Hadley Wickham可以说是R社区的一位大神级的人物。他先后写出了17个R包,包括目前统计图形方面的大热门ggplot2。作者自述其研究兴趣在于发展使数据分析变简单的工具特别是超越传统统计的数据清理,组织和探索方法。

为说明plyr包的特点和优势所在,下面看两个例子:

(1)对于简单的问题,plyr和apply函数的效果差不多
> m<-matrix(c(1:4,1,4,1:6),ncol=3)
> apply(m,1,mean)
[1] 1.666667 3.333333 3.000000 4.000000
> aaply(m,1,mean)
       1 2 3 4
1.666667 3.333333 3.000000 4.000000

(2)下面来个复杂点的
取鸢尾花iris数据集,对每一种花,建立一个线性回归模型,并给出结果。

> attach(iris)
> head(iris)
 Sepal.Length Sepal.Width Petal.Length Petal.Width Species
1 5.1 3.5 1.4 0.2 setosa
2 4.9 3.0 1.4 0.2 setosa
3 4.7 3.2 1.3 0.2 setosa
4 4.6 3.1 1.5 0.2 setosa
5 5.0 3.6 1.4 0.2 setosa
6 5.4 3.9 1.7 0.4 setosa

建立回归方程,
model <- function(x){ lm(Speal.Length~Speal.Width, data=x)}
使用apply函数族,需要分割,计算和合并(最少需要三个语句):
> pieces <- split(iris,list(iris$Species))
> models <- lapply(pieces,model)
#这两句也可替代为models<- by(iris[, 1:4], Species, model)
> result <- lapply(models,coef)
> do.call('rbind',result)

用pylr包只需要两句:
> result1 <- dlply(iris,.(Species),model)
> result2 <- ldply(result1,function(x) coef(x))

至于for语句,就不用写了吧,地方不够。

  • pylr包的使用

(1)命名规则
pylr的基本函数集如下(根据1.7.1版):
 

R语言数据转换——plyr包

命名规则:前三行是基本类型。
根据输入类型和输出类型:a=array,d=data frame,l=list,_表示输出放弃。第一个字母表示输入,第2个字母表示输出。
后两行是对应apply族的replicates和mapply这两个函数,分别表示n次重复和多元函数参数的情况,第2个字母还是表示输出类型。
从命名特点来看,我们不需要列出每个函数的情况了,只要从输入和输出两方面分别讨论即可。
 
(2)参数说明

这些函数有两到三个主要的参数,依赖于输入的类型:
. a*ply( .data, .margins, .fun, ..., .progress = "none")
. d*ply( .data, .variables, .fun, ..., .progress = "none")
. l*ply( .data, .fun, ..., .progress = "none")
参数.data是我们要用来分片-计算-合并的;参数.margins或者.variables描述了分片的方式;
参数.fun表示用来处理的函数,其它更多的参数是传递给处理函数的;参数.progress用来控制显示一个进度条。

(3)输入

输入类型有三种,每一种类型给出了如何进行分片的不同方法。
简单来说:
a*ply( ):数组(包括矩阵和向量)按维数分为低维的片。
d*ply( ):数据框被变量组合分成子集。
l*ply( ):列表的每个元素就是一个分片。

因此,对输入数据集的分片,不是取决于数据的结构,而是取决于所采用的方法。
一个对象采用a*ply( )分片必须对应dim( )且接受多维的索引;采用d*ply( )分片,要利用split( )并强制转换为列表;采用l*ply( ),需要用length() and [。
所以数据框可以被传递给a*ply( ),可以象2维的矩阵那样处理,也可以传递给l*ply( ),被视为一个向量的列表。

三种类型各自的特点:
(a): 输入数组(a*ply( ))
a*ply( )的分片特点在于.margins参数,它和apply很相似。
对于2维数组,.margins可以取1,2,或者c(1:2),对应2维数组的3种分片方式。
如图,

R语言数据转换——plyr包



对于3维数组,则有7种分片方式:

R语言数据转换——plyr包



.margins对应更高维的情况,可能会面临一种爆发式的组合。

(b)输入数据框(d*ply( ))

使用d*ply时,需要特别指定分组所用的变量或变量函数,它们会被首先计算,然后才是整个数据框。
有下面几种指定方式:
• .(var1)。按照变量var1的值来对数据框分组
•多重变量 .(a,b,c)。将按照三个变量的交互值来分组。

R语言数据转换——plyr包



这种形式输出的时候,有点复杂。如果输出为数组,则数组会有三个维度,分别以a,b,c的值作为维数名。如果输出为数据框,将会包含a,b,c取值的三个额外的列。如果输出为列表,则列表元素名为按周期分割的a,b,c的值。

•作为列名的字符向量:c("var1", "var2")。
•公式~ var1 + var2。


(c)输入列表(l*ply( ))
l*ply( )不需要描述如何分片的函数,因为列表本身就是按照元素的分划。使用l*ply( )相当于a*ply( )作用于一维数组的效果。
 

 

原文:http://site.douban.com/182577/widget/notes/10567181/note/246634257/

          及其他几篇综合