我:=在将所有 data.frames 转换为 data.tables 后立即使用时收到警告:
library(data.table) #Win R-3.5.1 x64 data.table_1.12.2
df1 <- data.frame(A=1, B=2)
df2 <- data.frame(D=3)
lapply(mget(ls()), function(x) {
if (is.data.frame(x)) {
setDT(x)
}
})
df1[, rn:=.I]
Run Code Online (Sandbox Code Playgroud)
警告消息: In
[.data.table(df1, ,:=(rn, .I)) : Invalid .internal.selfref 通过获取 data.table 的(浅)副本检测和修复,以便 := 可以通过引用添加此新列。早些时候,这个 data.table 已被 R 复制(或使用 structure() 或类似方法手动创建)。避免 names<- 和 attr<- 目前在 R 中(而且很奇怪)可能会复制整个 data.table。使用 set* 语法来避免复制:?set、?setnames 和 ?setattr。如果此消息没有帮助,请将您的用例报告给 data.table 问题跟踪器,以便修复根本原因或改进此消息。
下面也生成相同的警告:
df3 <- data.frame(E=3)
df4 <- data.frame(FF=4)
for (l in list(df3, df4)) setDT(l)
df3[, rn:=.I]
Run Code Online (Sandbox Code Playgroud)
一项一项的打字有效但乏味
df5 <- data.frame(G=5)
setDT(df5)
df[, rn := .I] #no warning
Run Code Online (Sandbox Code Playgroud)
将所有 data.frames 转换为 data.tables 的惯用方法是什么?
有关的:
setDT对名称/符号进行操作,同时get返回对象的值。您可以构造 setDT 表达式并对其进行评估:
library(data.table)
df1 <- data.frame(A=1, B=2)
df2 <- data.frame(D=3)
for(x in ls()){
if (is.data.frame(get(x))) {
eval(substitute(setDT(x), list(x=as.name(x))))
}
}
rm(x)
df1[, rn:=.I]
Run Code Online (Sandbox Code Playgroud)
我会使用循环而不是lapply避免并发症(例如,使用评估环境)。
有点晚了,但这似乎是一个很棒的\xe2\x80\x94和罕见的\xe2\x80\x94用途eapply()(以及list2env())。当然,这是另一种选择,当然不是断言这是惯用的方式。
library(data.table)\ndf1 <- data.frame(A=1, B=2)\ndf2 <- data.frame(D=3)\n\nlist2env(eapply(.GlobalEnv, function(x) {if(is.data.frame(x)) {setDT(x)} else {x}}), .GlobalEnv)\n\ndf1[, rn:=.I]\ndf1\n A B rn\n1: 1 2 1\nRun Code Online (Sandbox Code Playgroud)\n\n一些时间和内存使用情况:
\n\nset.seed(0L)\nsz <- 1e7\ndf1 <- data.frame(A=rnorm(sz))\ndf2 <- data.frame(B=rnorm(sz))\ndf3 <- copy(df1)\ndf4 <- copy(df2)\n\nmicrobenchmark::microbenchmark(unit="ms", times=1L,\n assign_mtd = {\n for (x in ls()) {\n if (is.data.frame(get(x))) {\n assign(x, as.data.table(get(x)))\n }\n }\n },\n eval_sub_mtd = {\n for(x in ls()){\n if (is.data.frame(get(x))) {\n eval(substitute(setDT(x), list(x=as.name(x))))\n }\n }\n },\n eapply_mtd = {\n list2env(eapply(.GlobalEnv, function(x) {\n if (is.data.frame(x)) setDT(x) else x\n }), .GlobalEnv)\n }\n)\nRun Code Online (Sandbox Code Playgroud)\n\n时间安排:
\n\nUnit: milliseconds\n expr min lq mean median uq max neval\n assign_mtd 115.922802 115.922802 115.922802 115.922802 115.922802 115.922802 1\n eval_sub_mtd 3.293358 3.293358 3.293358 3.293358 3.293358 3.293358 1\n eapply_mtd 1.913802 1.913802 1.913802 1.913802 1.913802 1.913802 1\nRun Code Online (Sandbox Code Playgroud)\n