Overview
我比较熟悉data.table
,没有那么多dplyr
。我读过一些dplyr小插图以及 SO 上出现的例子,到目前为止我的结论是:
-
data.table
and dplyr
速度相当,除非有很多(即 >10-100K)组,以及在其他一些情况下(参见下面的基准)
-
dplyr
具有更易于访问的语法
-
dplyr
抽象(或将)潜在的数据库交互
- 有一些细微的功能差异(请参阅下面的“示例/用法”)
2.在我心目中并没有多大分量,因为我相当熟悉data.table
,尽管我知道对于这两者的新用户来说这将是一个重要因素。我想避免争论哪个更直观,因为这与我从已经熟悉的人的角度提出的具体问题无关data.table
。我还想避免讨论“更直观”如何导致更快的分析(当然是正确的,但同样,这不是我在这里最感兴趣的)。
Question
我想知道的是:
- 对于熟悉这些包的人来说,是否存在使用一个或另一个包更容易编码的分析任务(即所需的击键与所需的深奥程度的某种组合,其中每种击键较少是一件好事)。
- 与另一个包相比,在一个包中执行分析任务的效率是否显着提高(即超过 2 倍)。
One 最近的问题让我更多地思考这个问题,因为直到那时我才想到dplyr
会提供超出我已经可以做的事情data.table
。这里是dplyr
解决方案(Q末尾的数据):
dat %.%
group_by(name, job) %.%
filter(job != "Boss" | year == min(year)) %.%
mutate(cumu_job2 = cumsum(job2))
这比我的黑客尝试要好得多data.table
解决方案。就是说,好data.table
解决方案也相当不错(感谢 Jean-Robert、Arun,并注意这里我更喜欢单一语句而不是严格的最佳解决方案):
setDT(dat)[,
.SD[job != "Boss" | year == min(year)][, cumjob := cumsum(job2)],
by=list(id, job)
]
后者的语法可能看起来非常深奥,但如果您习惯的话,它实际上非常简单data.table
(即不使用一些更深奥的技巧)。
理想情况下,我希望看到一些很好的例子dplyr
or data.table
方式更加简洁或者性能更好。
Examples
Usage
-
dplyr
不允许返回任意行数的分组操作(来自艾迪的问题,注意:这看起来将在dplyr 0.5另外,@beginneR 展示了一种潜在的解决方法,使用do
在对@eddi问题的回答中)。
-
data.table
支持滚动连接(感谢@dholstius)以及重叠连接
-
data.table
内部优化形式的表达式DT[col == value]
or DT[col %in% values]
for speed通过自动索引它使用二分查找同时使用相同的基本 R 语法。See here了解更多细节和一个小基准。
-
dplyr
提供函数的标准评估版本(例如regroup
, summarize_each_
)可以简化编程使用dplyr
(注意编程使用data.table
绝对是可能的,只需要一些仔细的思考、替换/引用等,至少据我所知)
基准测试
- I ran 我自己的基准并发现这两个包在“拆分应用组合”风格分析中具有可比性,除非存在大量组(> 100K)
data.table
变得更快。
- @Arun跑了一些连接基准,表明
data.table
规模比dplyr
随着组数量的增加(使用软件包和 R 最新版本中的最新增强功能进行更新)。另外,尝试获取时的基准独特的价值观 has data.table
快约 6 倍。
- (未经验证)有
data.table
较大版本的组/应用/排序速度提高 75%dplyr
较小的速度快 40% (评论中的另一个问题,谢谢达纳斯)。
- 马特,主要作者
data.table
, has 基准分组操作data.table, dplyr和蟒蛇pandas最多 20 亿行(RAM 中约 100GB).
- An 80K 组的旧基准 has
data.table
快约 8 倍
Data
这是我在问题部分展示的第一个例子。
dat <- structure(list(id = c(1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 2L, 2L,
2L, 2L, 2L, 2L, 2L, 2L), name = c("Jane", "Jane", "Jane", "Jane",
"Jane", "Jane", "Jane", "Jane", "Bob", "Bob", "Bob", "Bob", "Bob",
"Bob", "Bob", "Bob"), year = c(1980L, 1981L, 1982L, 1983L, 1984L,
1985L, 1986L, 1987L, 1985L, 1986L, 1987L, 1988L, 1989L, 1990L,
1991L, 1992L), job = c("Manager", "Manager", "Manager", "Manager",
"Manager", "Manager", "Boss", "Boss", "Manager", "Manager", "Manager",
"Boss", "Boss", "Boss", "Boss", "Boss"), job2 = c(1L, 1L, 1L,
1L, 1L, 1L, 0L, 0L, 1L, 1L, 1L, 0L, 0L, 0L, 0L, 0L)), .Names = c("id",
"name", "year", "job", "job2"), class = "data.frame", row.names = c(NA,
-16L))