在以下两种情况下,使用一个相对于另一个有什么优点/缺点? 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)
}
答案 0 :(得分:0)
尽管相似,但返回列表和环境却有所不同。 来自Advanced R:
通常,环境类似于列表,但有四个重要例外:
环境中的每个名称都是唯一的。
环境中的名称没有排序(即,询问环境的第一个元素是什么没有意义)。
环境有一个父级。
环境具有参考语义。
从技术上讲,环境由两个部分组成:框架和父环境,该框架包含名称-对象绑定(其行为很像命名列表)。不幸的是,R中不一致使用了“框架”。例如,parent.frame()不能为您提供环境的父框架。相反,它为您提供了调用环境。在调用环境中将对此进行更详细的讨论。
从帮助中:
help(new.env)
环境由框架或命名对象的集合以及指向封闭环境的指针组成。最常见的例子是函数调用局部变量的框架。它的外壳是定义功能的环境(除非随后进行了更改)。封闭环境与父框架有所区别:后者(由parent.frame返回)是指函数调用者的环境。由于混淆非常容易,因此最好不要在环境中使用“父母”(尽管存在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