我在列表中有一堆data.tables。我想将unique()
应用于列表中的每个data.table,但这样做会破坏我的所有data.table密钥。
以下是一个例子:
A <- data.table(a = rep(c("a","b"), each = 3), b = runif(6), key = "a")
B <- data.table(x = runif(6), b = runif(6), key = "x")
blah <- unique(A)
在这里,blah
仍然有一把钥匙,世界上的一切都是正确的:
key(blah)
# [1] "a"
但是,如果我将data.tables添加到列表并使用lapply()
,则密钥会被破坏:
dt.list <- list(A, B)
unique.list <- lapply(dt.list, unique) # Keys destroyed here
lapply(unique.list, key)
# [[1]]
# NULL
# [[2]]
# NULL
这可能与我没有真正理解“通过引用分配键”意味着什么,因为我还有其他问题,键已经消失了。
所以:
修改
对于它的价值,可怕的for
循环也可以正常工作:
unique.list <- list()
for (i in 1:length(dt.list)) {
unique.list[[i]] <- unique(dt.list[[i]])
}
lapply(unique.list, key)
# [[1]]
# [1] "a"
# [[2]]
# [1] "x"
但这是R,而for
循环是 evil 。
答案 0 :(得分:9)
有趣的是,请注意这两种不同结果之间的差异
lapply(dt.list, unique)
lapply(dt.list, function(x) unique(x))
如果使用后者,结果如您所料。
看似意外的行为是由于第一个lapply
声明的事实
调用unique.data.frame
(即来自{base}
)而第二个调用unique.data.table
答案 1 :(得分:5)
好问题。事实证明,它记录在?lapply
中(参见注释部分):
由于历史原因,lapply创建的调用未被评估, 并编写了代码(例如bquote),依赖于此。这个 表示录制的呼叫始终为FUN(X [[0L]],...)形式, 将0L替换为当前整数索引。这通常不是 问题,但它可以是如果FUN使用sys.call或match.call或如果它 一个利用这个调用的原始函数。 这意味着它 使用包装器调用原始函数通常更安全,因此例如 在R 2.7.1中需要lapply(ll,function(x)is.numeric(x))来确保 is.numeric的方法调度正确发生。