【问题标题】:data.table is copied when using spread()?使用 spread() 时复制 data.table?
【发布时间】:2017-10-26 15:58:34
【问题描述】:

这是一个示例data.table

set.seed(123)
mydt <- data.table(id = 1:100, x = sample(LETTERS[1:6], size = 100, replace = TRUE), group = paste0("group", sample(1:3, size = 100, replace = TRUE)), prob = runif(100, 0, 1))

我使用tydir::spread 从长格式转为宽格式

mydt2 <- mydt %>% spread(group, prob)

然后我想像在

中那样定义新列
mydt2[!is.na(group1), new.col := x]

如果我这样做,我会收到以下警告

Warning message:
In `[.data.table`(mydt2, !is.na(group1), `:=`(myscale, x)) :
 Invalid .internal.selfref detected and fixed by taking a (shallow) copy

等,而如果我改为运行它

mydt2 <- copy(mydt %>% spread(group, prob))
mydt2[!is.na(group1), myscale := x]

我没有收到任何警告。我不明白这种行为。任何人都可以提供帮助吗?使用copy() 是解决这个问题的正确方法吗?

【问题讨论】:

  • 标题可能信息量不大。如果有请更新
  • tidyr::spread 搞砸了内部结构,然后data.table 修复(因此警告);而在copy 期间创建的新data.table 自动具有正确的内部结构。这里的内部结构是指为 iirc 列预先分配的内存。
  • 如果你坚持使用spread,那么我只会接受警告。或者使用dcast(mydt, id + x ~ group)
  • "然后我想定义新列" -- 坚持使用 data.table 语法或 tidyverse 语法(使用 dtplyr);混合和匹配不是一个好主意。使用 dplyr + dtplyr mydt %&gt;% tidyr::spread(group, prob) %&gt;% mutate(new.col = replace(x, is.na(group1), NA)) 工作得很好。
  • 使用为data.table 实现的dcast。它类似于spread,你不应该有同样的问题。

标签: r data.table tidyr


【解决方案1】:

我认为使用dcast 是可行的方法。但是,使用tidyr::spread 的可能解决方案是将setDT() 添加到管道调用中,即,

set.seed(123)

# install.packages(c("data.table"), dependencies = TRUE)
library(data.table)

mydt <- data.table(id = 1:100, x = sample(LETTERS[1:6], size = 100, replace = TRUE),
                   group = paste0("group", sample(1:3, size = 100, replace = TRUE)),
                   prob = runif(100, 0, 1)
                   )

class(mydt)
mydt2 <- mydt %>% tidyr::spread(group, prob) %>% setDT()

mydt2[!is.na(group1), new.col := x]

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-05-25
    • 1970-01-01
    • 2020-06-21
    • 1970-01-01
    • 1970-01-01
    • 2019-03-31
    • 1970-01-01
    • 2016-09-16
    相关资源
    最近更新 更多