dplyr的mutate函数有哪些data.table的替代方案?

12

我正在学习R语言,但我不确定是将重点放在dplyr还是data.table上。Dplyr有非常好的语法,但据我了解,它在每次操作时都会复制数据框,这可能是一个缺点。

有一件事我无法弄清楚,那就是mutate的替代方法。

如果我有

df %>% group_by(foo) %>% mutate(
    bar  = cumsum(baz),
    q    = bar * 3.14)

我可以做类似于某事的事情。

df[,c("bar"):=list(cumsum(baz)),by=foo]
df$q <- df$bar*3.14

在data.table中有没有更好的方法来做这件事?


1
请提供可重现的示例,好吗? - Ben Bolker
首先,在你的第一行中,你不需要使用 clist。你的第二行有点突然回到了基本的 R 语法。为什么你突然又在使用 <-$?为什么不像你的第一行那样做一些类似于 df[,q:=bar*3.14] 的事情呢? - David Arenburg
除了个人偏好之外,使用一种或另一种语法有什么区别吗?我的意思是,在第一行中,由于“...,by=foo]”,我需要那种语法。 - zapp0
1
你自己提到过,你不想复制你的数据。所以 <-$ 会进行复制。如果你在数据表范围内使用 :=,你就可以避免复制。这就是 := 的全部意义 - 它通过引用进行更新。 - David Arenburg
<- 和 ? 会复制一份吗?哇,这有点违反直觉。抱歉,我不理解内部机制,也无法从语法中看出会复制。那么使用 mutate 的好处是它会为整个操作做一次拷贝吗?另一方面,我读到说它在与 data.table 一起使用时存在一个错误,并且它不使用浅拷贝。 - zapp0
在R中,除了data.table函数(如:=setnames等)之外的几乎所有操作都会生成副本。 - Max Ghenis
2个回答

14

你可以只做这个:

# some test data:
df <- data.table(baz = 1:10, foo = c(rep(1, 5), rep(2, 5)))

df[, bar := cumsum(baz), by = foo]
df[, q := bar*3.14]

虽然它是双行的,但非常易读且易写。


14

使用 data.table 的惯用方式是:

dt[, c("bar", "q") := {
       tmp = cumsum(baz)
       list(tmp, tmp*3.14)
     }, by = foo]

data.table 在同一时间内同时计算 j-expression,而不是分开计算(故意这样做),因此,除非将更新后的值存储在变量中,否则无法引用该值。

这样可以避免许多意外情况。一个有用的场景是:

dt[, c("a", "b") := list(pmin(a,b), pmax(a,b))]

:= 的行为与基本相同,只是它通过引用更新输入对象。它不等同于 mutate


1
谢谢您提供额外的pminpmax示例,这真的有助于说明概念。 - cmo
@Arun,我不理解这里的“dt [,c(”a“,”b“):= list(pmin(a,b),pmax(a,b))]”示例。它是什么意思? - Deb
1
@deb,那个j是一起被评估的。如果首先将a评估为pmin(a, b),那么b将始终是b,因为pmax(a, b)将与新值的a进行比较。 - Arun

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接