没有直接/简单的答案,因为这两个软件包的理念在某些方面有所不同。因此,不可避免地要做出一些妥协。这是您可能需要解决/考虑的一些问题。
涉及i
(==filter()
和slice()
dplyr中)的运算
假设DT
有10列。考虑以下data.table表达式:
DT[a > 1, .N]
DT[a > 1, mean(b), by=.(c, d)]
(1)给出DT
where列中的行数a > 1
。(2)返回与(1)中相同表达式的mean(b)
分组依据。c,d
i
常用的dplyr
表达式是:
DT %>% filter(a > 1) %>% summarise(n())
DT %>% filter(a > 1) %>% group_by(c, d) %>% summarise(mean(b))
显然,数据表代码更短。此外,它们还具有更高的存储效率1。为什么?因为在(3)和(4)中,首先filter()
返回所有10列的行,所以在(3)中,我们只需要行数,而在(4)中,我们只需要列即可b, c, d
进行连续操作。为了克服这个问题,我们必须在select()
列apriori中:
DT %>% select(a) %>% filter(a > 1) %>% summarise(n())
DT %>% select(a,b,c,d) %>% filter(a > 1) %>% group_by(c,d) %>% summarise(mean(b))
必须强调两个软件包之间的主要哲学差异:
在中data.table
,我们希望将这些相关的操作放在一起,这样就可以查看j-expression
(从同一函数调用)并意识到在(1)中不需要任何列。i
计算中的表达式,.N
它只是给出行数的逻辑矢量的和。整个子集永远不会实现。在(2)中,仅列b,c,d
在子集中实现,其他列被忽略。
但是dplyr
,该理念是具有这样的功能正好做一两件事好。(至少目前)没有办法判断之后的操作是否filter()
需要我们过滤的所有列。如果您想高效地执行此类任务,则需要提前考虑。在这种情况下,我个人认为它是不合逻辑的。
请注意,在(5)和(6)中,我们仍然a
对不需要的列进行子集化。但是我不确定如何避免这种情况。如果filter()
函数有一个参数来选择要返回的列,我们可以避免此问题,但是函数将不仅仅执行一项任务(这也是dplyr的设计选择)。
通过引用进行子分配
dplyr将永远不会通过引用进行更新。这是两个软件包之间的另一个巨大(哲学上的)区别。
例如,在data.table中,您可以执行以下操作:
DT[a %in% some_vals, a := NA]
它 仅在满足条件的那些行上a
通过引用更新列。目前,dplyr会在内部深度复制整个data.table以添加新列。@BrodieG在回答中已经提到了这一点。
但是,在实施FR#617时,可以用浅表副本代替深表副本。同样相关:dplyr:FR#614。请注意,仍然会始终复制您修改的列(因此速度稍慢/内存效率较低)。将无法通过引用更新列。
其他功能
在data.table中,您可以在连接时进行聚合,这很容易理解,并且由于中间连接的结果从未实现,因此可以提高内存效率。查看此帖子以获取示例。您目前无法使用dplyr的data.table / data.frame语法执行此操作。
dplyr的语法也不支持data.table的滚动联接功能。
我们最近在data.table中实现了重叠联接,以在间隔范围内联接(这里是一个示例),这是当前的一个单独函数foverlaps()
,因此可以与管道运算符(magrittr / pipeR?-从未尝试过)一起使用。
但最终,我们的目标是将其集成到其中,[.data.table
以便我们可以收获其他功能,例如分组,在加入时聚合等,这些功能将具有与上述相同的局限性。
从1.9.4版开始,data.table使用辅助键实现自动索引,以基于常规R语法的快速基于二进制搜索的子集。例如:DT[x == 1]
并且DT[x %in% some_vals]
会在首次运行时自动创建一个索引,然后使用二进制搜索将其用于从同一列到快速子集的连续子集。此功能将继续发展。查看此要点,以简短了解此功能。
从filter()
为data.tables实现的方式来看,它没有利用此功能。
dplyr的功能是它还使用相同的语法提供了数据库接口,而data.table目前还没有。
因此,您将不得不权衡这些(可能还有其他要点),并根据您是否可以接受这些折衷做出决定。
高温超导
(1)请注意,提高内存效率会直接影响速度(尤其是随着数据变大),因为瓶颈在大多数情况下是将数据从主内存移到缓存中(并尽可能多地利用缓存中的数据-减少缓存未命中-以减少对主存储器的访问)。这里不做详细介绍。
dplyr
用于数据表的方法,但是数据表也有其自己的可比较方法