【问题标题】:how can I mutate in dplyr without losing order?我怎样才能在 dplyr 中进行变异而不丢失顺序?
【发布时间】:2014-03-10 02:17:44
【问题描述】:

使用data.table 我可以执行以下操作:

library(data.table)
dt = data.table(a = 1:2, b = c(1,2,NA,NA))
#   a  b
#1: 1  1
#2: 2  2
#3: 1 NA
#4: 2 NA

dt[, b := b[1], by = a]
#   a b
#1: 1 1
#2: 2 2
#3: 1 1
#4: 2 2

dplyr 中尝试相同的操作,但是数据被a 打乱/排序:

library(dplyr)
dt = data.table(a = 1:2, b = c(1,2,NA,NA))
dt %.% group_by(a) %.% mutate(b = b[1])
#  a b
#1 1 1
#2 1 1
#3 2 2
#4 2 2

(除此之外,上面还对原始dt 进行了排序,考虑到dplyr 不就地修改的理念,这让我有些困惑——我猜这是dplyr 如何与data.table)

dplyr 的实现方式是什么?

【问题讨论】:

  • 我猜这是因为group_by 在内部调用了setkey。基本上,它没有ad hoc by。但我可能在这里错了。
  • 请注意,使用常规 R 数据框时不会发生这种情况。
  • 这是一个错误。可以在github上提交吗?
  • @hadley 你的意思是原始 dt 的排序还是两者都有?
  • @eddi 我很确定这是同一个问题,所以两者都是。

标签: r data.table dplyr


【解决方案1】:

在当前的 dplyr 开发版本中(最终将 成为 dplyr 0.2) 数据帧和数据之间的行为不同 表:

library(dplyr)
library(data.table)

df <- data.frame(a = 1:2, b = c(1,2,NA,NA))
dt <- data.table(df)

df %.% group_by(a) %.% mutate(b = b[1])

## Source: local data frame [4 x 2]
## Groups: a
## 
##   a b
## 1 1 1
## 2 2 2
## 3 1 1
## 4 2 2

dt %.% group_by(a) %.% mutate(b = b[1])

## Source: local data table [4 x 2]
## Groups: a
## 
##   a b
## 1 1 1
## 2 1 1
## 3 2 2
## 4 2 2

发生这种情况是因为 group_by() 应用于 data.table 假设索引将自动执行setkey() 未来的运营速度更快。

如果有强烈的感觉这是一个糟糕的默认设置,我很乐意更改它。

【讨论】:

  • 谢谢,我认为很明显您希望data.framedata.table 之间的行为相同,并且data.frame 行为是正确的
  • @eddi 计数器参数:dplyr 应该在可能的情况下默认利用 data.table 的性能。
  • @hadley,理想的版本是在group_by 期间允许adhoc-bysetkey。如果无法实现这种设计,我个人会选择adhoc-by,就像最近在 1.9.0+ 中进行的内部优化一样,adhoc-by 的速度非常快。另外,由于 setkey 操作必须重新排序整个数据(想想 biggggg 数据),因此它没有开销。此外,您在其顶部添加copy,这将使内存和时间要求更高。考虑到这一切,如果你只能选择两者中的一个,我会选择adhoc-by
  • 我怀疑你这样做是否会提高速度 - 我相当肯定 dt[, b := b[1], by = a] 总是比 setkey(dt, a); dt[, b := b[1], by = a] 快。但是,即使您确实获得了性能提升,也不应该为了性能而牺牲正确性。
  • 也许两者兼有会更好。例如,Here's a more complex case 同时使用了 adhoc-bykeys
猜你喜欢
  • 1970-01-01
  • 2018-03-26
  • 1970-01-01
  • 2021-09-17
  • 2010-12-05
  • 2022-10-01
  • 1970-01-01
  • 1970-01-01
  • 2023-01-25
相关资源
最近更新 更多