R语言学习 第九篇:plyr包
在数据分析中,整理数据的本质可以归纳为:对数据进行分割(Split),然后应用(Apply)某些处理函数,最后将结果重新组合(Combine)成所需的格式返回,简单描述为:Split - Apply - Combine,各个步骤的作用是:
- Split:把要处理的数据分割成小片断,常用的函数是split(),subset();
- Apply:对每个小片断独立进行操作,常用的是apply家族函数,plyr包核心函数;
- Combine:把片断重新组合,常用的函数是unlist()函数。
这个过程可以通过Base包的apply家族函数来实现,apply家族函数包括了apply、sapply、lapply、tapply、aggregate等,可以应用于数据分析的各个阶段。
plyr包是apply家族函数的升级版本,使用plyr包可以实现:在一个函数内同时完成“Split - Apply - Combine”,并且,plyr包实现R类型(vector, list, data.frame)之间的分组变换,基本上可以取代Base包中的apply家族函数。
plyr包对核心函数的命名采用统一的格式:**ply,所有的函数名都由5个字符组成,且最后三个字符是ply,函数名的第一个字符代表输入数据的类型,第二个字符代表输出数据的类型,R类型的简写是:
- d:data.frame
- l:list
- a:array,vector,matrix
- r:代表replicate,重复多次
- m:多输入
- _:舍弃输出结果
这种统一的命名格式,使得plyr包的函数更容易记忆和使用,但是,plyr包不是预装于R语言中,使用之前,需要加载和引用plyr包:
install.packages("plyr")
library(plyr)
一,plyr包函数
plyr包用于在R中实现split-apply-combine的模式,这中模式在数据分析中是极其常见的,通过把数据分解为小的分片,然后在分片上做操作,最后把结果组合在一起,以解决复杂的分析问题。因此,当遇到复杂的数据分析问题时,一般都需要把复杂的问题分组,然后在每个分组上做操作,最终把每个分组上的结果组合到一起。plyr包的函数很多,除了**ply的核心函数之外,还有一些辅助函数,在处理数据时,都十分有用。
1,ddply
plyr包中最常用的函数是ddply()函数,该函数对数据框进行操作,对每一行调用一个函数,并返回数据框类型:
ddply(.data, .variables, .fun = NULL, ...)
参数注释:
- .data:函数处理的数据框;
- .variables:要进行拆分的变量名称,传递变量的格式是: .(col_name),就是把进行分组的变量名包含在.()中;
- .fun:应用到每行的函数
- ...:传递到fun的其他参数
对于参数fun,有两种赋值方式:
第一种: 如果使用colwise()函数,那么这使ddply函数把参数fun应用于每一列,除了参数.variable指定的数据列之外,例如:
ddply(diamonds,.(color),colwise(mean))
第二种: 使用summarize函数对指定的列执行操作,更为灵活,例如:
> ddply(diamonds,.(color),summarize,avg_price=mean(price),avg_carat=mean(carat))
color avg_price avg_carat
1 D 3169.954 0.6577948
2 E 3076.752 0.6578667
.....
2,each函数
plyr包的each()函数,能够把多个函数整合到一个函数中,每一个函数必须只能返回一个数值:
each(...)
使用each()函数,可以使函数aggregate()同时调用多个函数:
> aggregate(cbind(price,carat)~cut+color,diamonds,each(mean,sum))
cut color price.mean price.sum carat.mean carat.sum
1 Fair D 4291.061 699443.000 0.9201227 149.9800000
2 Good D 3405.382 2254363.000 0.7445166 492.8700000
......
3,rename函数
按照名字对变量重命名:
rename(x, replace, warn_missing = TRUE, warn_duplicated = TRUE)
参数注释:
- x: 重命名的对象
- replace:命名的向量,格式是:c(new_name=old_name,...)
使用rename函数对数据框的变量进行重命名,例如:
rename(mtcars, c("disp" = "displacement"))
4,arrange函数
按照数据框的变量对数据框排序,注意,arrange()函数不会保留行名称(row.names)
arrange(df, ...)
例如,按照变量cyl和disp,对数据框mtcars进行排序:
# sort mtcars data by cylinder and displacement
mtcars[with(mtcars, order(cyl, disp)), ]
# Same result using arrange: no need to use with(), as the context is implicit
arrange(mtcars, cyl, disp)
5,mutate函数
对数据框进行转换,或增加新的变量,或替换已经存在的变量,该函数和transfrom函数十分相似,不过,mutate()函数是递进式的,这使得后期的转换可以使用早期创建的变量。
# Things transform can't do
mutate(airquality, Temp = (Temp - ) / 1.8, OzT = Ozone / Temp)
6,name_rows函数
在设计时,没有plyr函数会保留行名称(row names)。如果想保留行名称,可以使用name_rows()把行名称转换为显式的列值,在执行为相应的plyr操作之后,再使用name_rows把列值转换为行名称。
name_rows(df)
参数df :数据框对象,拥有 rownames,或者显式的列名 .rownames
二,拆分-应用-组合
在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
三,使用apply家族函数实现分组聚合
在apply家族函数中,每个函数都用于特定的数据类型:
- apply函数只能用于矩阵,
- lapply函数能够用于向量和列表(list),其工作原理是把一个函数应用于一个列表中的每个元素上,并且把结果作为列表返回;
- sapply处理列表,返回向量。
- mapply函数,把调用的函数应用到多个列表的每一个元素中。
- tapply函数用于分组聚合运算,在研究数据时,有时需要对数据按照特定的字段进行分组,然后统计各个分组的数据,这就是SQL语法中的分组聚合。
在数据分析中,使用Base包实现”拆分-应用-合并“ 显得十分繁琐,可以使用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包实现分组聚合
函数daply的作用是分割数据框,对每个分组应用聚合函数,最后把每个分组的聚合值组合起来,以数组的形式返回:
daply(.data, .variables, .fun = NULL, ...)
参数注释:
- .data:数据框,存储用于分析的数据;
- .variables:分组字段,指定分组字段的格式是 .(col_name);
- .fun:应用于每个分组的函数,有两种方式,上文有详细介绍。
为了计算每个player的平均得分,可以使用daply()函数,例如,
unlist(daply(players_scores,.(player),summarize,varScore=mean(score)))
在示例中,daply()函数返回的类型是list,通过unlist()函数转换为向量。至于为什么返回的是list,而不是数组,我也很疑惑。
参考文档:
R语言学习 第九篇:plyr包的更多相关文章
- R语言学习 第一篇:变量和向量
R是向量化的语言,最突出的特点是对向量的运算不需要显式编写循环语句,它会自动地应用于向量的每一个元素.对象是R中存储数据的数据结构,存储在内存中,通过名称或符号访问.对象的名称由大小写字母.数字0-9 ...
- R语言学习-基础篇1
###第一周:R基础 rm(list = ls()) #ctr+L###矩阵相乘,函数diag()a=matrix(1:12,nrow=3,ncol=4)b=matrix(1:12,nrow=4,n ...
- R语言学习-基础篇
从五月10日开始自学R in action,将我的学习所得逐渐发布在博客上. chapter1.新手上路 工作空间:存储着所有用户定义的对象(向量,矩阵,函数,数据框,列表): 当前的工目录保存是R用 ...
- R语言学习 第二篇:矩阵和数组
向量是一维的,只有行这一个维度,没有其他维度.R可以创建更高维度的数据对象,例如,矩阵.数据框.数组,索引高维度的对象时,需要使用元素的下标.这些对象的下标都使用中括号[]和索引,第一个维度是row, ...
- R语言学习笔记:glue包实现变量传参
glue包介绍 glue包可用于自定义变量,然后通过传参的方式,对字符串部分内容进行自适应修改. 例如:可将日期赋值为:date = as.Date("2019-12-05"),然 ...
- R语言学习 第四篇:函数和流程控制
变量用于临时存储数据,而函数用于操作数据,实现代码的重复使用.在R中,函数只是另一种数据类型的变量,可以被分配,操作,甚至把函数作为参数传递给其他函数.分支控制和循环控制,和通用编程语言的风格很相似, ...
- R语言入门级实例——用igragh包分析社群
R语言入门级实例——用igragh包分析社群 引入—— 本文的主要目的是初步实现R的igraph包的基础功能,包括绘制关系网络图(social relationship).利用算法进行社群发现(com ...
- R语言︱文本挖掘之中文分词包——Rwordseg包(原理、功能、详解)
每每以为攀得众山小,可.每每又切实来到起点,大牛们,缓缓脚步来俺笔记葩分享一下吧,please~ --------------------------- 笔者寄语:与前面的RsowballC分词不同的 ...
- R语言·文本挖掘︱Rwordseg/rJava两包的安装(安到吐血)
每每以为攀得众山小,可.每每又切实来到起点,大牛们,缓缓脚步来俺笔记葩分享一下吧,please~ --------------------------- R语言·文本挖掘︱Rwordseg/rJava ...
随机推荐
- 线程池ThreadPoolExecutor源码解读研究(JDK1.8)
一.什么是线程池 为什么要使用线程池?在多线程并发开发中,线程的数量较多,且每个线程执行一定的时间后就结束了,下一个线程任务到来还需要重新创建线程,这样线程数量特别庞大的时候,频繁的创建线程和销毁线程 ...
- ibatis annotations 注解方式返回刚插入的自增长主键ID的值
mybatis提供了注解方式编写sql,省去了配置并编写xml mapper文件的麻烦,今天遇到了获取自增长主键返回值的问题,发现相关问答比较少,还好最后还是圆满解决了,现把重点记录一下,解决问题的关 ...
- 初探JodaTime
在学习java之初时就使用过jdk自带的java.util.Calendar ,近期的项目中需要达到类似功能的时候使用了JodaTime. Joda-Time 令时间和日期值变得易于管理.操作和理解. ...
- PHP之取得当前时间函数方法
PHP之取得当前时间函数方法 PHP之取得当前时间函数方法文章提供了php的几种获取当前时间的函数,date,time等,同时告诉我如何解决时区问题.php教程取得当前时间函数文章提供了php的几种获 ...
- Office远程代码执行漏洞(CVE-2017-11882)复现
昨晚看到的有复现的文章,一直到今天才去自己复现了一遍,还是例行记录一下. POC: https://github.com/Ridter/CVE-2017-11882/ 一.简单的生成弹计算器的doc文 ...
- bat脚本:windows下一键启动zookeeper+kafka
bat脚本:windows下一键启动zookeeper+kafka 把下面两行代码存为bat文件,双击执行即可.注意更改相应的目录 这里用ping来控制时间(先zookeeper,ping 4 次后 ...
- Java爬虫爬取网站电影下载链接
之前有看过一段时间爬虫,了解了爬虫的原理,以及一些实现的方法,本项目完成于半年前,一直放在那里,现在和大家分享出来. 网络爬虫简单的原理就是把程序想象成为一个小虫子,一旦进去了一个大门,这个小虫子就像 ...
- 有关Redis的Add和Set方法的比较
测试发现,如果key已经存在,则调用Redis.Add(key, value)则不能添加或修改此key的内容value: 这样的话,我们在添加一个key和value的时候,不得不判断一次Contain ...
- Python 中列表生成式和生成器
列表生成式 即List Comprehensions,是Python内置的非常简单却强大的可以用来创建list的生成式. 举个例子,要生成list [1,2,3,4,5,6,7,8,9,10]可以用l ...
- 基于PLC-C#串口通讯,温度检测和转速监控的c#/.Net实现。
我司为五金加工企业,其中有一条喷涂车间和流水线,客户要求能实时监控炉温温度.流水线速,并设置上下限值,达到上下限时报警. 开始考虑过USB的温度采集器,但是却没有找到带USB的光电开关,并且线路长度受 ...