【问题标题】:Is a saved and loaded data.table with qs a correct data.table是一个保存和加载的 data.table 与 qs 一个正确的 data.table
【发布时间】:2022-01-07 20:44:28
【问题描述】:

当我再次加载 data.table 时,我将 data.table 保存为 qs 文件,它的行为似乎不像 data.table。

澄清我的意思。这是一个例子:

library(data.table)
library(qs)

n <- 10000
dt <- data.table(x = rnorm(n), y = rnorm(n))

cnames <- colnames(dt)
dt[, new_col_1 := 1]
cnames
[1] "x"         "y"         "new_col_1"

cnames <- colnames(dt)
dt[, new_col_2 := 1]
cnames
[1] "x"         "y"         "new_col_1" "new_col_2"

所以函数colnames() 是指向data.table dt 的列名的指针。 但是,如果我对保存和加载的 data.table 执行相同操作,就会发生这种情况

n <- 10000
dt <- data.table(x = rnorm(n), y = rnorm(n))
qs::qsave(dt, "dt_saved.qs")

dt_saved <- qs::qread("dt_saved.qs")
cnames <- colnames(dt_saved)
dt_saved[, new_col_1 := 1]
cnames
[1] "x" "y"

cnames <- colnames(dt_saved)
dt_saved[, new_col_2 := 1]
cnames
[1] "x"         "y"         "new_col_1" "new_col_2"

所以只有在修改data.table之后,函数colnames()才是一个指针。

一些额外的信息:

R version 4.1.1 (2021-08-10)
qs_0.25.1
data.table_1.14.2

【问题讨论】:

  • 当然它仍然有 data.table 类,否则它不会允许 := 所以我认为它与加载数据后不存在/有效的 internal.selfref 有关。因此,您将 colnames 分配给 cnames,但还没有将其更新到的参考。当你分配一个新列时, internal.selfref 被设置,所以它知道从那时起 colnames 中的下一个新列。

标签: r data.table


【解决方案1】:

这是因为你存储的文件中的data.table没有(或没有有效的)内部指针,所以它不能通过引用更新(因为没有引用)。

您也可以使用 dput 进行演示。

# create a data.table, but it has no internal.selfref
dt <- structure(list(x = c("A", "B", "C"), y = 1:3), row.names = c(NA, 
-3L), class = c("data.table", "data.frame"))

cnames <- colnames(dt)
dt[, new_col_1 := 1]

# Warning message:
# In `[.data.table`(dt, , `:=`(new_col_1, 1)) :
#   Invalid .internal.selfref detected and fixed by taking a (shallow) copy of the data.table so that := can add this new column by reference. At an earlier point, this data.table has been copied by R (or was created manually using structure() or similar). Avoid names<- and attr<- which in R currently (and oddly) may copy the whole data.table. Use set* syntax instead to avoid copying: ?set, ?setnames and ?setattr. If this message doesn't help, please report your use case to the data.table issue tracker so the root cause can be fixed or this message improved.

cnames

# [1] "x" "y"

因此您可以看到引用是从您分配新列的点创建的,但它无法更新 cnames,因为那里没有引用。

您可以在加载数据后立即使用 setDT,这样您也可以在 cnames 上获得参考

dt <- structure(list(x = c("A", "B", "C"), y = 1:3), row.names = c(NA, 
-3L), class = c("data.table", "data.frame"))

setDT(dt) # create reference so cnames updates on reference as well

cnames <- colnames(dt)
dt[, new_col_1 := 1]
cnames
# [1] "x"         "y"         "new_col_1"

【讨论】:

    猜你喜欢
    • 2015-07-26
    • 2018-04-16
    • 2019-04-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-04-02
    • 2014-01-08
    • 2020-05-08
    相关资源
    最近更新 更多