在R中返回Mutable或Immutable变量的函数

时间:2017-02-17 11:26:27

标签: r data.table immutability mutable

我认为这个问题与R中的Mutable Vs Immutable对象的概念有关,它可能是一个“生成问题”。我使用函数names()和函数setnames()的{​​{1}}函数遇到了这个问题。我确信这是预期的行为,但对我来说这是非常令人惊讶的,我相信这不仅与data.table有关。

想象一下,我有一个名为names()的data.table,其中包含两列a和b:

dt

如果您打印dt <- data.table(a = 1:5, b= 1:5) oldNames <- names(dt) ,它显然会显示:

oldNames

但是,如果你使用oldNames [1] "a" "b" 来追加dt的名字:

setnames()

变量setnames(dt,oldNames,c("aNew","bNew")) 的内容已更改。

oldNames

我知道在Python中,这是某些数据类型(可变的)中的预期行为,而不是其他数据类型(不可变的)。在R中,还有这种双切断术吗?

对我来说,“预期”行为是变量oldNames [1] "aNew" "bNew" 存储列的名称,而不依赖于data.table的未来变化。例如,使用oldNames函数不会发生这种情况:

length()

有关此行为或解释的一些有用信息的任何链接都将非常感激,以及编码的方式是什么,因此{d}修改后L <- length(dt) L [1] 2 dt[,c:=1:5] L [1] 2 不会更改其内容。

1 个答案:

答案 0 :(得分:1)

我认为这是由于data.table包的实现。在R中,多个符号可以指向同一个符号,但它通常不会引起问题,因为对象将在修改时被复制,例如:

a <- c(1,2)
b <- a
# To check the memory address,
# `a` and `b` are pointed to the same object since `b` does not modify `a`.
pryr::address(a)
[1] "0x1a735620"
pryr::address(b)
[1] "0x1a735620"
# Then we modify `a`
a <- c(1,3)
# We will notice that the address of `a` has changed
# since there are modifications, but `b` not.
pryr::address(a)
[1] "0x1a72f168"
pryr::address(b)
[1] "0x1a735620"

从我有限的知识来看,data.table包有点特殊,因为它会通过一些操作修改对象。参见:

dt <- data.table(a = 1:5, b= 1:5)
n1 <- names(dt)

pryr::address(n1)
[1] "0x18aeffe0"

setnames(dt, c("a","b"), c("aa","bb"))

n2 <- names(dt)
pryr::address(n2) # identical to the address of `n1`
[1] "0x18aeffe0"

n1
[1] "aa" "bb"

我认为data.table包没有识别出有一个变量指向其name属性,从而导致了问题。我认为这是一个错误,你可能想用&#34; data.table&#34;标记问题。

在当前时间,您可以使用n <- c(names(dt))来存储名称,这样,R会考虑c()修改名称属性并将其存储在不同的内存地址中。

顺便说一句,R确实有可变对象,请参阅Reference classR6 objects; - )

问候;

更新:

参见?data.table :: copy和?data.table :: setnames

引用?data.table :: copy:

  

执行'dt_names = names(DT)'时可能需要'copy()'。由于   R&#39> copy-on-modify ,'dt_names'仍指向同一位置   内存为'名称(DT)'。因此,现在通过引用修改'DT',   通过添加新列,'dt_names'也将更新。避免   这个,必须显式地复制:'dt_names&lt; - copy(names(DT))'。

它们当然不常见于R,data.table可以这样做,因为它使用R的C接口。

会话信息:

> sessionInfo()
R version 3.3.2 (2016-10-31)
Platform: x86_64-suse-linux-gnu (64-bit)
Running under: openSUSE Tumbleweed

locale:
 [1] LC_CTYPE=en_US.UTF-8       LC_NUMERIC=C               LC_TIME=en_US.UTF-8       
 [4] LC_COLLATE=en_US.UTF-8     LC_MONETARY=en_US.UTF-8    LC_MESSAGES=en_US.UTF-8   
 [7] LC_PAPER=en_US.UTF-8       LC_NAME=C                  LC_ADDRESS=C              
[10] LC_TELEPHONE=C             LC_MEASUREMENT=en_US.UTF-8 LC_IDENTIFICATION=C       

attached base packages:
[1] stats     graphics  grDevices utils     datasets  methods   base     

other attached packages:
[1] pryr_0.1.2          data.table_1.9.6    magrittr_1.5        personalutils_0.1.0

loaded via a namespace (and not attached):
[1] tools_3.3.2      Rcpp_0.12.9      stringi_1.1.2    codetools_0.2-15
[5] stringr_1.1.0    chron_2.3-47