2

我有 21 个全局环境变量,每个变量都包含大量数据。我想在函数中通过引用来访问这些变量,但我想参数化它们的名称,例如,如果我有 SPdata、NEdata、FRdata 等...... 21 个变量,我想知道如何通过传递在函数中访问它们只有“国家名称”(即“SP、“NE”、“FR”等)无需创建副本(因为它们的大小都超过 300 兆)。Get 似乎制作了一个副本(对我的大小来说效率低下)数据)。我可以这样做吗?我目前正在到处使用获取

cData <- get(paste(cCode, "data", sep = "")) 

是的,我知道我应该将它们全部放入全局环境中的列表中,但现在为时已晚,我不想重构所有代码。只是我的“获取”变得内存效率低下,循环中的多次访问可能很慢。例如,我可以像访问列表一样访问每个变量吗?

我应该使用 countryData = list(SPdata, NEdata, FRdata..etc),使用 countryData[[paste(cCode, "data", sep = "")]] 访问它们,但现在为时已晚。

我应该补充一点,我确实打算更改函数中的一些值,并且 get() 确实会在更改时复制,从下面的不同地址可以看出。

> .Internal(inspect(a))
@101b7bcf8 14 REALSXP g0c1 [NAM(2)] (len=1, tl=0) 1
> g <- function() {x <- get("a"); x; x <- 2; .Internal(inspect(x))}
> g()
@101cea648 14 REALSXP g0c1 [NAM(2)] (len=1, tl=0) 2
> 
4

2 回答 2

6

get不生成副本。例如,在下面的代码中,我们看到它x不是副本,a.1因为它位于同一地址,即 at 0x00000000077a0010

> a.1 <- 1:1000000
> .Internal(inspect(a.1))
@0x00000000077a0010 13 INTSXP g0c7 [NAM(1)] (len=1000000, tl=0) 1,2,3,4,5,...
> g <- function() { x <- get("a.1"); .Internal(inspect(x)); max(x) }
> g()
@0x00000000077a0010 13 INTSXP g0c7 [NAM(2)] (len=1000000, tl=0) 1,2,3,4,5,...
[1] 1000000

如果您修改一个变量(附加是一种修改),那么它将被复制。这里x开始于0x00000000075b95d8但在被修改后被复制到0x000000000744d8e0并且在被附加到之后再次被复制到0x000000000754c5e8

> n <- 10000
> x <- 1:n
> .Internal(inspect(x))
@0x00000000075b95d8 13 INTSXP g0c7 [NAM(1)] (len=10000, tl=0) 1,2,3,4,5,...
> f <- function() {
+ .GlobalEnv$x[[n]] <- 0
+ .Internal(inspect(x))
+ x <<- c(x, 0)
+ .Internal(inspect(x))
+ }
> f()
@0x000000000744d8e0 14 REALSXP g0c7 [NAM(1)] (len=10000, tl=0) 1,2,3,4,5,...
@0x000000000754c5e8 14 REALSXP g0c7 [NAM(1)] (len=10001, tl=0) 1,2,3,4,5,...

Above we modified the global variable from within the function but even if we had done it outside the function it still would have been copied.

于 2013-03-30T03:02:47.273 回答
4

快速的:

  • R 语义是“写入时复制”,因此如果您不更改这些变量的内容,则不会进行复制

  • R有内存分析,你真的确定正在制作副本吗?有关内存分析的基础知识,请参阅“编写 R 扩展”。

  • 如果您确实确定这些正在被复制,则可以通过强制使用外部指针来防止这种情况发生,方法是使用 XPtr 对象或使用部署外部指针(如 bigmemory)的包装器。

于 2013-03-30T02:45:56.140 回答