在以下两种情况下,使用其中一种有什么优势/劣势?Case-I 将其输出作为环境返回,Case-II 将其输出作为列表返回。
案例一:
function(x) {
ret <- new.env()
ret$x <- x
ret$y <- x^2
return(ret)
}
案例二:
function(x) {
ret <- list()
ret$x <- x
ret$y <- x^2
return(ret)
}
在以下两种情况下,使用其中一种有什么优势/劣势?Case-I 将其输出作为环境返回,Case-II 将其输出作为列表返回。
案例一:
function(x) {
ret <- new.env()
ret$x <- x
ret$y <- x^2
return(ret)
}
案例二:
function(x) {
ret <- list()
ret$x <- x
ret$y <- x^2
return(ret)
}
尽管相似,但返回列表和环境存在差异。从高级 R:
通常,环境类似于列表,但有四个重要例外:
环境中的每个名称都是唯一的。
环境中的名称没有顺序(即,询问环境的第一个元素是什么是没有意义的)。
一个环境有一个父级。
环境具有引用语义。
从技术上讲,环境由两个组件组成,框架包含名称-对象绑定(并且行为很像命名列表),以及父环境。不幸的是,“框架”在 R 中的使用不一致。例如,parent.frame() 不会为您提供环境的父框架。相反,它为您提供调用环境。这在调用环境中有更详细的讨论。
从帮助:
help(new.env)
环境由一个框架或命名对象的集合和一个指向封闭环境的指针组成。最常见的例子是函数调用的局部变量框架;它的外壳是定义函数的环境(除非随后更改)。封闭环境与父框架不同:后者(由 parent.frame 返回)指的是函数调用者的环境。因为很容易混淆,所以最好不要在环境中使用“parent”(尽管存在 parent.env 函数)。
从函数的文档中:
e1 <- new.env(parent = baseenv()) # this one has enclosure package:base.
e2 <- new.env(parent = e1)
assign("a", 3, envir = e1)
ls(e1)
#[1] "a"
但是ls
会给出创建的环境:
ls()
#[1] "e1" "e2"
您可以像列表一样访问您的环境对象:
e1$a
#[1] 3
玩弄你的功能:
f1 <- function(x) {
ret <- new.env()
ret$x <- x
ret$y <- x^2
return(ret)
}
res <- f1(2)
res
#<environment: 0x0000021d55a8a3e8>
res$y
#[1] 4
f2 <- function(x) {
ret <- list()
ret$x <- x
ret$y <- x^2
return(ret)
res2 <- f(2)
res2
#$x
#[1] 2
#$y
#[1] 4
res2$y
#[1] 4
他们的表现非常相似,根据microbenchmarking
:
microbenchmark::microbenchmark(
function(x) {
ret <- new.env()
ret$x <- x
ret$y <- x^2
return(ret)
},
function(x) {
ret <- list()
ret$x <- x
ret$y <- x^2
return(ret)
},
times = 500L
)
#Unit: nanoseconds
# #expr
# function(x) { ret <- new.env() ret$x <- x ret$y <- x^2 #return(ret) }
# function(x) { ret <- list() ret$x <- x ret$y <- x^2 #return(ret) }
# min lq mean median uq max neval
# 0 1 31.802 1 100 801 500
# 0 1 37.802 1 100 2902 500
他们返回相同大小的对象:
object.size(res)
#464 bytes
object.size(res2)
#464 bytes
并且您始终可以从环境 ( list2env
) 和逆 ( as.list
) 生成列表:
L <- list(a = 1, b = 2:4, p = pi, ff = gl(3, 4, labels = LETTERS[1:3]))
e <- list2env(L)
e$ff
# [1] A A A A B B B B C C C C
#Levels: A B C
as.list(e)
#$ff
# [1] A A A A B B B B C C C C
#Levels: A B C
#
#$p
#[1] 3.141593
#
#$b
#[1] 2 3 4
#
#$a
#[1] 1