gpt4 book ai didi

r - 通过使用环境避免复制

转载 作者:行者123 更新时间:2023-12-01 02:11:52 27 4
gpt4 key购买 nike

在 Hadley 的 Advanced R 书中,有一节是关于将环境用作“大型物体的容器”(参见下面的施加)。我正在寻找一些示例来说明这种方法的最佳实践。我看了here但没有发现任何明确解决这个问题的内容。

如果相关,我的应用程序是一个 Shiny 的应用程序,其中应用程序环境中的数据与导出的函数(在 R/中)共享。另见此 question .

用于管理数据流的函数是here . r_env是 Shiny 的环境。如果在应用程序外部调用分析函数,该函数会在用户退出应用程序或在全局环境中查找转储到 R(studio) 的数据。

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

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

编辑

我希望基于数据如何传递给函数的差异。使用几种不同的方法,差异似乎很小。哈德利所指的(未命名的)生物导体包中使用的方法有什么不同?

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/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com