return R 中可变或不可变变量的函数
Functions that return a Mutable or Immutable variables in R
我认为这个问题与 R 中可变对象与不可变对象的概念有关,可能是 "beginer question"。我 运行 使用包 data.table
的函数 names()
和 setnames()
函数解决了这个问题。我确信这是预期的行为,但对我来说这是非常令人惊讶的,而且我确信这不仅与 names()
.
有关
假设我有一个名为 dt
的 data.table,其中包含两列 a 和 b:
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
的内容已更改。
oldNames
[1] "aNew" "bNew"
我知道在 Python 中,这是某些数据类型(可变数据类型)而非其他数据类型(不可变数据类型)的预期行为。 R里也有这种二分法吗?
对我来说,"expected" 行为是变量 oldNames
存储列的名称,它不依赖于 data.table 的未来变化。例如,对于 length()
函数,这不会发生:
L <- length(dt)
L
[1] 2
dt[,c:=1:5]
L
[1] 2
任何 link 关于此行为或解释的一些有用信息将不胜感激,以及编码方式是什么 oldNames
在 dt 修改后不会更改其内容。
我认为这是由于实施了 data.table 包。在 R 中,多个符号可以指向同一个东西,但通常不会造成问题,因为 object 会在修改时被复制,例如:
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包有点特殊,因为它会通过一些操作来修改object。参见:
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 属性,因此导致了这个问题。我认为这是一个错误,您可能想用 "data.table".
标记问题
目前可以使用n <- c(names(dt))
来存储names,这样R会认为c()
修改了name属性并存储在不同的内存地址。
顺便说一句,R 确实有可变的 objects,参见 Reference class
和 R6 objects
;-)
此致;
更新:
参见 ?data.table::copy 和 ?data.table::setnames
引用自 ?data.table::copy:
A ‘copy()’ may be required when doing ‘dt_names = names(DT)’. Due to
R's copy-on-modify, ‘dt_names’ still points to the same location in
memory as ‘names(DT)’. Therefore modifying ‘DT’ by reference now,
say by adding a new column, ‘dt_names’ will also get updated. To avoid
this, one has to explicitly copy: ‘dt_names <- copy(names(DT))’.
它们在R中当然不常见,data.table可以做到这一点,因为它使用了R的C接口。
Session 信息:
> 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
我认为这个问题与 R 中可变对象与不可变对象的概念有关,可能是 "beginer question"。我 运行 使用包 data.table
的函数 names()
和 setnames()
函数解决了这个问题。我确信这是预期的行为,但对我来说这是非常令人惊讶的,而且我确信这不仅与 names()
.
假设我有一个名为 dt
的 data.table,其中包含两列 a 和 b:
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
的内容已更改。
oldNames
[1] "aNew" "bNew"
我知道在 Python 中,这是某些数据类型(可变数据类型)而非其他数据类型(不可变数据类型)的预期行为。 R里也有这种二分法吗?
对我来说,"expected" 行为是变量 oldNames
存储列的名称,它不依赖于 data.table 的未来变化。例如,对于 length()
函数,这不会发生:
L <- length(dt)
L
[1] 2
dt[,c:=1:5]
L
[1] 2
任何 link 关于此行为或解释的一些有用信息将不胜感激,以及编码方式是什么 oldNames
在 dt 修改后不会更改其内容。
我认为这是由于实施了 data.table 包。在 R 中,多个符号可以指向同一个东西,但通常不会造成问题,因为 object 会在修改时被复制,例如:
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包有点特殊,因为它会通过一些操作来修改object。参见:
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 属性,因此导致了这个问题。我认为这是一个错误,您可能想用 "data.table".
标记问题目前可以使用n <- c(names(dt))
来存储names,这样R会认为c()
修改了name属性并存储在不同的内存地址。
顺便说一句,R 确实有可变的 objects,参见 Reference class
和 R6 objects
;-)
此致;
更新:
参见 ?data.table::copy 和 ?data.table::setnames
引用自 ?data.table::copy:
A ‘copy()’ may be required when doing ‘dt_names = names(DT)’. Due to R's copy-on-modify, ‘dt_names’ still points to the same location in memory as ‘names(DT)’. Therefore modifying ‘DT’ by reference now, say by adding a new column, ‘dt_names’ will also get updated. To avoid this, one has to explicitly copy: ‘dt_names <- copy(names(DT))’.
它们在R中当然不常见,data.table可以做到这一点,因为它使用了R的C接口。
Session 信息:
> 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