2 分组动作 group_by()
以上5个动词函数已经很方便了, 但是当它们跟分组操作这个概念结合起来时, 那才叫真正的强大! 当对数据集通过 group_by() 添加了分组信息后,mutate(), arrange() 和 summarise() 函数会自动对这些 tbl 类数据执行分组操作 (R语言泛型函数的优势).
例如: 对飞机航班数据按飞机编号 (TailNum) 进行分组, 计算该飞机航班的次数 (count = n()), 平均飞行距离 (dist = mean(Distance, na.rm = TRUE)) 和 延时 (delay = mean(ArrDelay, na.rm = TRUE))
planes <- group_by(hflights_df, TailNum)delay <- summarise(planes, count = n(), dist = mean(Distance, na.rm = TRUE), delay = mean(ArrDelay, na.rm = TRUE))delay <- filter(delay, count > 20, dist < 2000)
用 ggplot2 包作个图观察一下, 发现飞机延时不延时跟飞行距离没太大相关性:
ggplot(delay, aes(dist, delay)) + geom_point(aes(size = count), alpha = 1/2) + geom_smooth() + scale_size_area()
(图就不上了, 右键复制来的链接太凶残了, 看着像是现算的)
更多例子见 vignette("introduction", package = "dplyr")
另: 一些汇总时的小函数
- n(): 计算个数
- n_distinct(): 计算 x 中唯一值的个数. (原文为 count_distinct(x), 测试无用)
- first(x), last(x) 和 nth(x, n): 返回对应秩的值, 类似于自带函数 x[1], x[length(x)], 和 x[n]
注意: 分组计算得到的统计量要清楚样本已经发生了变化, 此时的中位数是不可靠的
3 连接符 %.%
包里还新引进了一个操作符, 使用时把数据名作为开头, 然后依次对此数据进行多步操作.
比如:
Batting %.% group_by(playerID) %.% summarise(total = sum(G)) %.% arrange(desc(total)) %.% head(5)
这样可以按进行数据处理时的思路写代码, 一步步深入, 既易写又易读, 接近于从左到右的自然语言顺序, 对比一下用R自带函数实现的:
head(arrange(summarise(group_by(Batting, playerID), total = sum(G)) , desc(total)), 5)
或者像这篇文章所用的方法:
totals <- aggregate(. ~ playerID, data=Batting[,c("playerID","R")], sum)ranks <- sort.list(-totals$R)totals[ranks[1:5],]
文章里还表示: 用他的 MacBook Air 跑 %.% 那段代码用了 0.036 秒, 跑上面这段代码则用了 0.266 秒, 运算速度提升了近7倍. (当然这只是一例, 还有其它更大的数字.)
更多请 ?"%.%", 至于这个新鲜的概念会不会和 ggplot2 里的 + 连接号一样, 发挥出种种奇妙的功能呢? 还是在实际使用中多体验感受吧.
感想
可以看到, 用 dplyr 所含函数实现的代码都要简洁易读得多, 说到底, R语言只是一个工具, 作为工具, 就是要拿来用的, 越称手越便利越简洁越好, 可是, 正如 Hadley Wickham 在2013年的访谈中提到的那样:
如果你用了8小时进行数据清理和数据整理,而只用了2小时进行建模,那么很明显,你希望了解如何将数据清理和整理的时间尽可能缩短。
反思之下, 本人也是将大把的时间花在了对数据的反复调整上, 或许是手生, 当然R语言在这方面也确实有一定不足, 大神又说了:
数据分析有两个瓶颈,一是我们的目标是什么,二是我们如何用计算机去实现。我现有的很多作品,如 ggplot2,plyr 和 reshape2,更关注的是如何更简单地表达你的目标,而不是如何让计算机算得更快。
这种内在的理念正是要将工具工具化, 把无谓的时间减少, 让精力用在真正需要考虑的地方. 正如 Vim 一样, 在投入一定的学习成本后, 继续用继续学, 不知不觉地就能心手如一, 想做什么, 就已经按下去了, 从而更多地思考要编辑什么, 而不必纠结于光标移动选择等细节. 这其中的巧妙之处在于: 实现过程要以人脑的思维运作方式为标准, 让工具来适应人, 以实现目的为导向, ggplot2 的图形图层语法也是如此. 不管是软件也好, 编程语言也好, 高效的方法都是相通的, 这也正是许多人努力的方向, 另外平素语出惊人的王垠最近也表达了类似观点.
顺便肖凯老师在网易云课堂新开的R语言初级教程里提到了十大必学R包的说法, 并把 plyr 列为之一, 有趣的是居然还有人在问答平台上求详情, 好奇之下放狗一搜, 原来出处在此 (脱水版), 其中 ggplot2 和 reshape2 是平时都有在用的, 还有实用的 knitr 和 Slidify , 其它就没什么发言权了.
深入学习
暂时没有太多的相关资料, 如欲进一步学习, 可参阅:
- dplyr 包自带的60页详细文档
- 其余几个vignettes (网页) 或 vignette(package = "dplyr") , 包含了数据库相关, 混合编程, 运算性能比较, 以及新的 window-functions 等内容.
简单看了下vignette("window-functions", package = "dplyr"), 提供了一系列函数, 扩展了原来只能返回一个数值的聚焦类函数(如sum(), mean())至返回等长度的值, 变成 cumsum()和 cummean(), 以及 n(), lead() 和 lag()等便捷功能. - plyr 包的相关文档: 主页
- 还有 data.table 包也是很强大的哦, 空下来可以学一学
暂无数据