我了解到data.table
在从函数返回时不会被复制。然而,在这种特殊情况下,它确实被复制了。有人可以解释一下为什么吗?
dt1 <- data.table(a=1)
dt2 <- data.table(b=1)
dt3 <- data.table(c=1)
address(dt1); address(dt2); address(dt3)
[1] "000000005E20D990"
[1] "00000000052301E8"
[1] "000000001D622210"
l <- list(a=dt1, b=dt2, c=dt3)
address(l$a); address(l$b); address(l$c)
$[1] "000000005E20D990"
$[1] "00000000052301E8"
$[1] "000000001D622210"
f <- function(dt) {setnames(dt, toupper(names(dt)))}
l <- Map(f, l)
address(l$a); address(l$b); address(l$c)
$[1] "000000001945C7B0"
$[1] "0000000066858738"
$[1] "000000001B021038"
dt1
$ A
$1: 1
dt2
$ B
$1: 1
dt3
$ C
$1: 1
所以是最后一行在进行复制。但以下内容不会复制。
address(dt1)
$[1] "000000005E20D990"
dt4 <- f(dt1)
address(dt4)
$[1] "000000005E20D990"
我错过了什么?
更新
正如大家指出的那样,map
或mapply
会进行复制。lapply
在上面的情况下可以工作,但我的实际代码需要函数中的多个输入。 我的理解是所有apply
函数使用相同的代码。 但事实并非如此。
Map
是对mapply
的封装,我认为复制发生在mapply
函数中。 - Rolandlapply
的源代码中,我注意到有这样一行代码:if (MAYBE_REFERENCED(tmp)) tmp = lazy_duplicate(tmp);
而在mapply
中则是if (MAYBE_REFERENCED(tmp)) tmp = duplicate(tmp);
。这可能是导致问题的原因。由于我不是R内部专家,所以不能确定。 - nicolaMap
或mapply
。然后使用lapply(seq_along(l), function(i) ...)
并使用i
迭代器对mapply
中使用的对象进行子集化,因此在您的示例中为l[[i]]
,可能还有更多,因为mapply
循环遍历多个对象。 - jangoreckil <- Map(f, l)
切换为简单的Map(f, l)
,它似乎可以正常工作。你很少需要使用set*
函数的返回值。 - Frankfuncdt<-f(dt1); address(funcdt)
显示相同的地址。换句话说,问题不在函数上,而是在Map
上。 - Dean MacGregor