我对data.table
比较熟悉,对dplyr
不太熟悉。我已经阅读了SO上出现的一些#1小插曲和示例,到目前为止我的结论是:
data.table
和dplyr
在速度上是可比的,除非有很多(即>10-100K)组,以及在其他一些情况下(见下面的基准)dplyr
具有更易于访问的语法dplyr
抽象(或将)潜在的数据库交互在我看来,2.没有多大分量,因为我对它相当熟悉data.table
,尽管我知道对于两者的新手来说,这将是一个很大的因素。我想避免争论哪个更直观,因为这与我从已经熟悉data.table
的人的角度提出的具体问题无关。我还想避免讨论“更直观”如何导致更快的分析(当然是真的,但同样,这不是我最感兴趣的)。
我想知道的是:
一个最近的SO问题让我更多地思考了这个问题,因为在那之前,我认为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
或data.table
的方式更简洁或性能更好。
dplyr
不允许返回任意行数的分组操作(从eddi的问题开始,注意:这看起来像是在dplyr 0.5中实现的,此外,在回答@eddi的问题时,@eginneR显示了使用do
的潜在解决方法)。data.table
支持滚动连接(感谢@dholstius)以及重叠连接data.table
在内部优化了速度到自动索引的DT[col == value]
或DT[col %in% values]
形式的表达式,它使用二分查找,同时使用相同的基本R语法。看这里用于更多细节和一个小基准。dplyr
提供了函数的标准评估版本(例如regroup
,summarize_each_
),可以简化dplyr
的编程使用(注意data.table
的编程使用绝对是可能的,只是需要一些仔细的思考,替换/引用等,至少据我所知)data.table
变得更快。data.table
的缩放比dplyr
更好(更新了两个包和最新版本的R的最新增强功能)。此外,尝试获得唯一值时的基准测试速度data.table
~6倍。data.table
的主要作者Matt拥有对#0、#2和python#3进行基准分组操作,最多20亿行(内存中约100GB)。data.table
~8倍这是我在问题部分展示的第一个例子。
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))