没有直接/简单的答案,因为这两个包的理念在某些方面有所不同.因此,一些妥协是不可避免的.以下是您可能需要解决/考虑的一些问题.
Operations involving i
(== filter()
and slice()
in dplyr)
假设DT
,比如10列.考虑这些数据.表表达式:
DT[a > 1, .N] ## --- (1)
DT[a > 1, mean(b), by=.(c, d)] ## --- (2)
(1) 给出列a > 1
所在的DT
中的行数.(2) 对于i
中与(1)相同的表达式,返回由c,d
分组的mean(b)
.
常用的dplyr
个表达是:
DT %>% filter(a > 1) %>% summarise(n()) ## --- (3)
DT %>% filter(a > 1) %>% group_by(c, d) %>% summarise(mean(b)) ## --- (4)
显然是数据.表格代码较短.此外,它们也是more memory efficient1.为什么?因为在(3)和(4)中,filter()
首先返回rows for all 10 columns,而在(3)中,我们只需要行数,在(4)中,我们只需要b, c, d
列来进行后续操作.要克服这一点,我们必须事先:
DT %>% select(a) %>% filter(a > 1) %>% summarise(n()) ## --- (5)
DT %>% select(a,b,c,d) %>% filter(a > 1) %>% group_by(c,d) %>% summarise(mean(b)) ## --- (6)
必须强调两个方案之间的一个主要哲学差异:
在data.table
中,我们希望将这些相关操作放在一起,这样就可以查看j-expression
(来自同一个函数调用),并意识到(1)中不需要任何列.计算i
中的表达式,.N
只是给出行数的逻辑向量的和;整个子集从未实现.在(2)中,只有第b,c,d
列在子集中具体化,其他列被忽略.
但在dplyr
中,哲学是让函数精确地做一件事well.(至少目前)无法判断filter()
之后的操作是否需要我们筛选的所有列.如果你想高效地完成这些任务,你需要提前思考.我个人觉得在这种情况下这是反直觉的.
请注意,在(5)和(6)中,我们仍然将不需要的第a
列作为子集.但我不知道如何避免这种情况.如果filter()
函数有一个参数来 Select 要返回的列,我们可以避免这个问题,但是该函数不会只执行一个任务(这也是dplyr设计的 Select ).
通过引用分配
dplyr将通过引用进行更新.这是两个软件包之间的另一个巨大(哲学)差异.
例如,在数据中.你可以做什么
DT[a %in% some_vals, a := NA]
只在满足条件的行上更新列a
by reference.目前dplyr深度复制整个数据.表内部添加一个新列@布罗迪格在回答中已经提到了这一点.
但在实现FR #617时,深度拷贝可以被浅层拷贝取代.也相关:dplyr: FR#614.请注意,您修改的列将始终被复制(因此速度较慢/内存效率较低).无法通过引用更新列.
其他功能
在数据中.由于这是一个中间过程,所以你永远无法理解这个结果.以this post为例.你(现在)不能吗使用dplyr的数据来实现这一点.表/数据.框架语法.
数据dplyr的语法也不支持table的rolling joins功能.
我们最近在数据中实现了重叠连接.表在区间范围内连接(here's an example),目前这是一个单独的函数foverlaps()
,因此可以与管道操作员一起使用(magrittr/pipeR?-我从未try 过).
但最终,我们的目标是将其集成到[.data.table
中,以便我们可以获得其他功能,如分组、加入时聚合等..其限制条件与上述相同.
从1.9.4开始,数据.表使用辅助键实现自动索引,用于基于常规R语法的快速二进制搜索子集.Ex:DT[x == 1]
和DT[x %in% some_vals]
将在第一次运行时自动创建索引,然后使用二进制搜索将索引用于从同一列到快速子集的连续子集.这一功能将继续发展.此功能的概述为this gist.
从数据实现filter()
的方式来看.表,它没有利用这个功能.
dplyr的一个特性是,它还提供了interface to databases个使用相同语法的数据.桌子现在不好.
因此,你必须权衡这些(可能还有其他几点),并根据这些权衡是否为你所接受来决定.
嗯
(1) 请注意,内存效率直接影响速度(尤其是当数据变得更大时),因为在大多数情况下,瓶颈是将数据从主存移动到缓存(并尽可能多地利用缓存中的数据,减少缓存未命中率,从而减少对主存的访问).这里不谈细节.