通过常规方法(例如ll["name"] <- NULL
)从列表中删除元素,导致整个列表被复制。通常,这是不明显的,直到数据集变得很大。
我有一个列表,其中包含十二个元素,每个元素的大小在0.25~2 GB之间。从此列表中删除三个元素大约需要十分钟才能执行(在相对较快的机器上)。
有没有办法从列表中放置元素?
我尝试了以下内容:
TEST <- list(A=1:20, B=1:5)
TEST[["B"]] <- NULL
TEST["B"] <- NULL
TEST <- TEST[c(TRUE, FALSE)]
data.table::set(TEST, "B", value=NULL) # ERROR
带内存信息的输出:
cat("\n\n\nATTEMPT 1\n")
TEST <- list(A=1:20, B=1:5)
.Internal(inspect(TEST))
TEST[["B"]] <- NULL
.Internal(inspect(TEST))
cat("\n\n\nATTEMPT 2\n")
TEST <- list(A=1:20, B=1:5)
.Internal(inspect(TEST))
TEST["B"] <- NULL
.Internal(inspect(TEST))
cat("\n\n\nATTEMPT 3\n")
TEST <- list(A=1:20, B=1:5)
.Internal(inspect(TEST))
TEST <- TEST[c(TRUE, FALSE)]
答案 0 :(得分:2)
我不知道如何在不复制它的情况下缩短矢量。下一个最好的方法是将元素设置为缺少NA
或NULL
。
根据?Extract
,您必须指定TEST[i] <- list(NULL)
才能将元素设置为NULL
。我的测试表明i
必须是整数或逻辑向量。
> TEST <- list(A=1:20, B=1:5); .Internal(inspect(TEST))
@27d2c60 19 VECSXP g0c2 [NAM(1),ATT] (len=2, tl=0)
@27dd9e0 13 INTSXP g0c6 [] (len=20, tl=0) 1,2,3,4,5,...
@2805c98 13 INTSXP g0c3 [] (len=5, tl=0) 1,2,3,4,5
ATTRIB:
@1f38be8 02 LISTSXP g0c0 []
TAG: @d3f478 01 SYMSXP g1c0 [MARK,LCK,gp=0x4000] "names" (has value)
@2807430 16 STRSXP g0c2 [] (len=2, tl=0)
@dc2628 09 CHARSXP g1c1 [MARK,gp=0x61] [ASCII] [cached] "A"
@dc25f8 09 CHARSXP g1c1 [MARK,gp=0x61] [ASCII] [cached] "B"
> TEST[2] <- list(NULL); .Internal(inspect(TEST)); TEST
@27d2c60 19 VECSXP g0c2 [MARK,NAM(1),ATT] (len=2, tl=0)
@27dd9e0 13 INTSXP g0c6 [MARK] (len=20, tl=0) 1,2,3,4,5,...
@d3fb78 00 NILSXP g1c0 [MARK,NAM(2)]
ATTRIB:
@1f38be8 02 LISTSXP g0c0 [MARK]
TAG: @d3f478 01 SYMSXP g1c0 [MARK,LCK,gp=0x4000] "names" (has value)
@2807430 16 STRSXP g0c2 [MARK] (len=2, tl=0)
@dc2628 09 CHARSXP g1c1 [MARK,gp=0x61] [ASCII] [cached] "A"
@dc25f8 09 CHARSXP g1c1 [MARK,gp=0x61] [ASCII] [cached] "B"
$A
[1] 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
$B
NULL
答案 1 :(得分:1)
正如@ JoshO'Brien在他的评论中所建议的那样,使用environments
代替lists
来将大对象存储在内存中会更有效率。根据我的经验,Environments
赋予了大量的时间和内存优势(对于大型对象存储):
元素查找时间。
您是否注意到在列表末尾访问对象可能会非常慢(几秒钟)?那是因为lists
不知道每个元素在内存中的位置,他们必须通过搜索list
(我认为)来找到每个元素。
另一方面,访问环境中的变量是即时的(它只需要搜索存储在环境中的变量名列表)。当列表元素很大时,这是显而易见的!
到位修改。
在环境中修改(或删除)变量时,仅复制单个对象。修改列表时,将在整个过程中复制整个列表。
使用环境
TEST <- new.env()
TEST <- as.environment(TEST)
rm(A, envir=TEST)
TEST$A <- 1:20
TEST$A
ls(pos=TEST)
(这相当于names(TEST)
)