在哈德利(Hadley)的Advanced R书中,有关于将环境用作“大型物体容器”的部分(请参见下文)。我正在寻找一些示例,以说明此方法的最佳实践。我看了here,但没有找到任何明确解决此问题的方法。

如果相关,我的应用程序是一个闪亮的应用程序,其中应用程序环境中的数据与导出的功能(在R /中)共享。另请参见此question

用于管理数据流的功能是herer_env是闪亮的环境。如果在应用程序外部调用了分析功能,则该功能会在用户退出应用程序时或在全局环境中查找转储到R(studio)的数据。

http://adv-r.had.co.nz/Environments.html#explicit-envs

“避免复制
由于环境具有参考语义,因此您绝不会意外创建副本。这使其成为用于大型物体的有用容器。这是生物导体包装的常用技术,通常必须管理大型基因组对象。 ”

编辑

我希望基于数据如何传递给函数的差异。使用一些不同的方法,差异似乎很小。 Hadley所指的(未命名的)生物导体包装所使用的方法有何不同?

library(ggplot2)
library(microbenchmark)
dat <- diamonds
dataset <- "dat"
r_env <- new.env()
r_env$dat <- diamonds

reg1 <- function(dataset)
    lm(price ~ carat + color, data = get(dataset))

reg2 <- function(dataset)
    lm(price ~ carat + color, data = r_env[[dataset]])

reg3 <- function(dat)
    lm(price ~ carat + color, data = dat)

microbenchmark(times = 100,
  reg1(dataset),
  reg2(dataset),
  reg3(dat)
)

Unit: milliseconds
          expr      min       lq     mean   median       uq      max neval
 reg1(dataset) 75.52479 85.50742 87.80560 87.57180 89.59216 96.34956   100
 reg2(dataset) 83.98896 85.51443 87.40334 87.00544 88.84889 94.01787   100
     reg3(dat) 61.00551 86.01789 88.15627 88.13501 90.48899 95.05454   100

最佳答案

对于列表和函数的参考语义,这是一个修改列表元素的函数

f = function (l) {
    l[[1]][1] = 2
    l
}


这是一个列表,它是函数应用前后的内部表示

> l = list(a=1:5, b=1:5)
> .Internal(inspect(l))
@b3baa80 19 VECSXP g0c2 [NAM(1),ATT] (len=2, tl=0)
  @a4133a8 13 INTSXP g0c3 [] (len=5, tl=0) 1,2,3,4,5
  @a4133f0 13 INTSXP g0c3 [] (len=5, tl=0) 1,2,3,4,5
ATTRIB:
  @894b670 02 LISTSXP g0c0 []
    TAG: @1406d18 01 SYMSXP g1c0 [MARK,NAM(2),LCK,gp=0x6000] "names" (has value)
    @b3baab8 16 STRSXP g0c2 [] (len=2, tl=0)
      @15c8f68 09 CHARSXP g1c1 [MARK,gp=0x61] [ASCII] [cached] "a"
      @17f47e8 09 CHARSXP g1c1 [MARK,gp=0x61] [ASCII] [cached] "b"
> .Internal(inspect(f(l)))
@b2da518 19 VECSXP g0c2 [NAM(1),ATT] (len=2, tl=0)
  @6d6b3f0 14 REALSXP g0c4 [] (len=5, tl=0) 2,2,3,4,5
  @a4133f0 13 INTSXP g0c3 [NAM(2)] (len=5, tl=0) 1,2,3,4,5
ATTRIB:
  @85031c8 02 LISTSXP g0c0 []
    TAG: @1406d18 01 SYMSXP g1c0 [MARK,NAM(2),LCK,gp=0x6000] "names" (has value)
    @b3baab8 16 STRSXP g0c2 [NAM(2)] (len=2, tl=0)
      @15c8f68 09 CHARSXP g1c1 [MARK,gp=0x61] [ASCII] [cached] "a"
      @17f47e8 09 CHARSXP g1c1 [MARK,gp=0x61] [ASCII] [cached] "b"


在函数调用之前,这部分

@b3baa80 19 VECSXP g0c2 [NAM(1),ATT] (len=2, tl=0)
  @a4133a8 13 INTSXP g0c3 [] (len=5, tl=0) 1,2,3,4,5
  @a4133f0 13 INTSXP g0c3 [] (len=5, tl=0) 1,2,3,4,5


是列表(VECSXP)和整数向量(INTSXP)。 @是数据的内存地址。函数调用后,我们有

@b2da518 19 VECSXP g0c2 [NAM(1),ATT] (len=2, tl=0)
  @6d6b3f0 14 REALSXP g0c4 [] (len=5, tl=0) 2,2,3,4,5
  @a4133f0 13 INTSXP g0c3 [NAM(2)] (len=5, tl=0) 1,2,3,4,5


整个列表和修改后的元素的地址已更改,但重要的是第二个元素的地址未更改。

人们会在环境中看到类似的行为,只是整体SXP不会改变。当然,当然还会引入参考语义(即使函数调用的返回值返回到另一个符号,原始环境也会发生变化),这可能是非常不希望的。

关于r - 通过使用环境避免复制,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/28655735/

10-16 20:48