R语言环境空间理解_r environment-程序员宅基地

技术标签: r语言  R语言  

环境空间 ( environment ) 对于刚接触 R 语言的我来说,是比较陌生的。虽然不了解它的运行原理,但也不影响我使用 R 语言。环境空间是 R 语言中关于计算机方面的底层设计,主要用于R语言是环境加载器。通过环境空间,封装了加载器的运行过程,让使用者在不知道底层细节的情况下,可以任意加载使用到的第三方的 R 语言程序包。

介绍

在R语言中,不管是变量,对象,或者函数,都存在于 R 的环境空间中,R程序在运行时都自己的运行时空间。R 语言的环境 (environment) 是由内核定义的一个数据结构,由一系列的、有层次关系的框架 (frame) 组成,每个环境对应一个框架,用来区别不同的运行时空间 (scope) 。

环境空间有一些特征,比如 每个环境空间要有唯一的名字;环境空间是引入类型的,非赋值类型;环境空间都有父环境空间,空环境是最顶层的环境空间,没有父空间;子环境空间会继承父环境空间的变量等。

环境的理解

关于环境的理解,先从新建一个环境开始:new.env(hash = TRUE, parent = parent.frame(), size = 29L)

  • hash 默认TRUE ,指使用 Hash Table 的结构
  • parent 默认当前环境,指定要创建环境的父环境
  • size 初始化环境大小
# 擦混关键环境env
env <- new.env()
env
## [1] <environment: 0x3d7eef0>
class(env)
## [1] "environment"

# 定义变量
env$a <- 123
env$b <- 'qwe'
ls(env)
## [1] "a" "b"

以上就是新建了一个父环境为当前环境的环境空间,在这个环境空间中可以定义自己的变量,并且可以使用环境$变量的方式访问环境内的变量。

环境空间的层次结构

那么所谓创建环境时的父环境又是什么呢,要理解这个就得来理解环境空间的层次结构了。R 语言中有五种环境的定义:当前环境、内部环境、父环境、空环境和包环境。

  • 当前环境,即用户环境,用户运行程序时的环境(<environment: R_GlobalEnv>)
  • 内部环境,构造出来的环境,使用new.env()构造出来的环境
  • 父环境,即环境空间的上一层环境,R语言中除了空环境之外所有环境都有父环境
  • 空环境,即顶层环境,没有父环境空间
  • 包环境,包封装的环境空间
# 当前环境,或者使用globalenv
environment()
## [1] <environment: R_GlobalEnv>
# 内部环境
new.env()
## [1] <environment: R_GlobalEnv>
# 父环境
parent.env(env)
## [1] <environment: R_GlobalEnv>
# 空环境
emptyenv()
## [1] <environment: R_EmptyEnv>
# 包环境
baseenv()
## [1] <environment: base>

既然环境空间是有层次的,那可以将从 env 到空环境的层次结构全部打印出来

# 递归打印环境空间,identical比较两者是否相同
parent.call <- function(env) {
    
  print(env)
  if(is.environment(env) & !identical(env, emptyenv())) {
     
    parent.call(parent.env(env))
  }
}

parent.call(env)
## <environment: 0x366bf18>
## <environment: R_GlobalEnv>
## <environment: package:purrr>
## attr(,"name")
## [1] "package:purrr"
## attr(,"path")
## [1] "/home/dingtao/R/x86_64-pc-linux-gnu-library/3.3/purrr"
## <environment: package:stats>
## attr(,"name")
## [1] "package:stats"
## attr(,"path")
## [1] "/usr/lib/R/library/stats"
## <environment: package:graphics>
## attr(,"name")
## [1] "package:graphics"
## attr(,"path")
## [1] "/usr/lib/R/library/graphics"
## <environment: package:grDevices>
## attr(,"name")
## [1] "package:grDevices"
## attr(,"path")
## [1] "/usr/lib/R/library/grDevices"
## <environment: package:utils>
## attr(,"name")
## [1] "package:utils"
## attr(,"path")
## [1] "/usr/lib/R/library/utils"
## <environment: package:datasets>
## attr(,"name")
## [1] "package:datasets"
## attr(,"path")
## [1] "/usr/lib/R/library/datasets"
## <environment: package:methods>
## attr(,"name")
## [1] "package:methods"
## attr(,"path")
## [1] "/usr/lib/R/library/methods"
## <environment: 0x20cb5d0>
## attr(,"name")
## [1] "Autoloads"
## <environment: base>
## <environment: R_EmptyEnv>

可以看到先是打印出来<environment: 0x366bf18>这是 env 的环境空间;接下来是作为 env 父空间的当前空间;再接下来是我导入的 purrr 包,其实这里还有很多,我给省略了,然后是六个基础包、Autoloads、base 包,最后是空环境。那么从R的导入顺序来看就是反过来的,先加载空环境,然后再一步步导入所需要的包,最后到达当前环境。

那么我们就可以访问到父环境以及爷爷环境等等中的变量,前提是未在当前环境中找到,它就会去父环境中寻找,一直找到空环境,若是还没有找到就会报错;但若是当前环境空间中已有相同名称的变量,那么你要么使用 rm 删除当前环境空间中的变量,要么指定环境变量访问变量,否则是访问不到指定环境空间中的变量的。

环境的操作

主要是一些命令的使用

# 基础命令
env1 <- new.env()  # 创建一个新环境
is.environment(env1)  # 判断是否是一个环境空间
environment()  # 查看当前环境空间
environment(ls)  # 查看函数中的环境空间
environmentName(baseenv())  # 查看环境空间的名字
environmentName(environment())
attr(env1, 'name') <- 'env1'  # 设置环境空间的名字,默认创建出来是没有名字的
env.profile(env1)  # 查看环境空间的属性值
rm(list=ls())  # 清空当前环境空间定义的所有对象
rm(x, envir=env1)  # 删除env1中的变量
ls(env1)  # 查看env1环境空间中的变量
x <- 1.5; y <- 2:10  # 定义环境空间中的变量
env1 <- new.env()
env1$x <- -10

# 环境空间变量取值
get('x', envir=env1)  # 取env1环境空间中的x值
get('y', envir=env1)  # 从env1环境空间中取从当前环境中继承的y值
# get('y', envir=env1, inherits=FALSE)  # 禁止环境空间的继承,会报错

# 重新赋值
assign('x', 77); x  # 重新赋值当前环境空间中的x值
assign('x', 99, envir=env1); env1$x  # 重新赋值环境空间中的x值
assign('y', 333, envir=env1, inherits=FALSE)  # 在没有继承的情况下给环境空间中的y赋值

# 变量在环境空间中是否存在
exists('x')
exists('x', envir=env1)
# exists('y', envir=env1, isherits=FALSE)  # 在没有继承的情况下y是否存在,会报错

# 查看函数的环境空间,来自pryr包
where('mean')
where('where')

函数的环境空间

在R语言中,变量、对象、函数都存在于环境空间中,而函数又可以有自己的环境空间,我们可以在函数内再定义变量、对象和函数,循环往复就形成了我们现在用的R语言环境系统。

一般情况,我们可以通过new.env()去创建一个环境空间,但更多的时候,我们使用的是函数环境空间。函数环境空间包括4方面的内容:

  • 封闭环境,每个函数都有一个且只有一个封闭环境空间,指向函数定义的环境空间
  • 绑定环境,给函数指定一个名字,绑定到函数变量,如fun1<-function(){1}
  • 运行环境,当函数运行时,在内存中动态产生的环境空间,运行结束后,会自动销毁
  • 调用环境,是指在哪个环境中进行的方法调用,如fun1<-function(){fun2()},函数fun2在函数fun1被调用
参数寻址补充

函数中的参数是惰性求值,不执行则不运算,只有在执行或者被调用的时候才会进行运算;函数体执行运算用到变量时若函数体中未定义,参数环境中也未定义,则会向全局环境中寻址;函数在被调用时若有缺省值,则局部参数被调用时会优先使用传入的参数,若未传入参数才会使用缺省值。

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/m0_61192794/article/details/120493263

智能推荐

python 视频教程推荐_求各位大佬推荐Python学习视频教程?-程序员宅基地

文章浏览阅读219次。一、零基础入门,国家精品课《Python语言程序设计》(免费)国家精品课《Python语言程序设计》,将在2018年9月18号开始报名,每周学习2~3个小时,共9周学时。走完这个学期,你就能够掌握Python语言基础了,请大家收藏好本帖。Python语言程序设计 - 北京理工大学​www.icourse163.org课程团队1. 嵩天,博士,北京理工大学计算机学院副教授。美国华盛顿大学(Washi..._python进阶视频课程推荐

React Native 集成native-echarts(图表插件)及代码示例_react-native-charts-程序员宅基地

文章浏览阅读6.3k次,点赞2次,收藏8次。React-Native 集成native-echarts(图表插件)_react-native-charts

mysql时间戳(秒)任意秒分组统计聚合实现_timestamp按秒group-程序员宅基地

文章浏览阅读1.2k次。开发过程中有一个需求,需要任意时间段进行聚合统计,例如 每5秒,每10分钟,每2小时 num值得的聚合_timestamp按秒group

PLC高手秘籍!实例讲解PLC故障排查_plc报警查询功能的作用-程序员宅基地

文章浏览阅读856次。PLC硬件损坏或软件运行出错的概率极低,检查故障时,重点应放在PLC的外围电气元件,PLC的故障大多数是外围接口信号故障,维修时,只要PLC有部分控制的动作正常,就不用怀疑PLC的程序问题。确认运算程序有输出,而PLC的接口没有输出,则为接口电路故障。PLC系统的硬件故障多于软件故障,大多是外部信号不满足或执行元件故障引起,而不是PLC系统的问题。可根据PLC输入、输出状态来判断故障。PLC的..._plc报警查询功能的作用

SQL Server 2019 的下载安装及后续与Java的连接_java 连接 sqlserver2019-程序员宅基地

文章浏览阅读3.1k次,点赞3次,收藏26次。SQL Server 2019 下载安装详解一、下载网址https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads二、安装步骤1.进入官网后的页面如下,在“还可以下载免费的专用版本”中选择下方“Developer版本”,点击下方“立即下载”按钮。2.下载后得到一个应用程序文件,双击并运行。3.在弹出的窗口选择安装类型 基本(B) 。4.选择语言 中文(简体),并点击 接受 。5.选择安装位置,根据个人需要决定,点击安_java 连接 sqlserver2019

一张图理清Vue中的生命周期和钩子函数_vue的执行过程与生命周期函数的关联图形-程序员宅基地

文章浏览阅读477次,点赞2次,收藏2次。前言Vue 框架的入口就是 Vue 实例,其实就是框架中的 view model ,它包含页面中的业务处理逻辑、数据模型等,它的生命周期中有多个事件钩子,让我们在控制整个Vue实例的过程时更容易形成好的逻辑。贴图下面的图片是在官方文档的图片上进行了解释说明,帮大家更好的理解这张图。代码贴上一个小案例辅助理解<!DOCTYPE html><html lang="..._vue的执行过程与生命周期函数的关联图形

随便推点

matlab2019使用仿真,simulink视频教程仿真建模matlab2019高级-程序员宅基地

文章浏览阅读698次。原标题:simulink视频教程仿真建模matlab2019高级simulink视频教程仿真建模matlab2019高级观看地址https://ke.qq.com/course/465006?tuin=b844ecf1、 simulink基础知识1.1 simulink概述1.2 simulink工作原理1.3 simulink组成与环境2、 simulink仿真基础2.1 simulink基本操..._matlab2019如何进行电路仿真

关于阿里短信配置InvalidDayuStatus.Malformed : The specified dayu status is wrongly formed.的问题_invaliduserstatus.malformed 阿里云短信-程序员宅基地

文章浏览阅读1.8k次。关于阿里短信配置InvalidDayuStatus.Malformed : The specified dayu status is wrongly formed.的问题 1.这个问题主要是之前与阿里大于使用的短信接口不同将最新阿里提供的官方sdk导入&lt;dependency&gt; &lt;groupId&gt;com.aliyun&lt;/groupId&gt; &lt;..._invaliduserstatus.malformed 阿里云短信

【2019.05.23】JS逆向——破解裁判文书网参数(vl5x,guid )爬虫 超级详细_爬取中国裁判-程序员宅基地

文章浏览阅读2.6k次,点赞2次,收藏16次。文书网免责声明引言本文仅用于个人学习与技术交流,如果有人用于其它其它用途与我一点点关系都没有~如果有啥地方不恰当地方可以联系我删除,不要举报或者有其他的操作总之好好学习社会主义核心价值观保护共产主义接班人中国裁判文书网http://wenshu.court.gov.cn/一、分析请求参数1.找到请求一点搜索的小技巧,我们很容易就找到了我们需要的请求小技巧:..._爬取中国裁判

OpenGL_opengl中的translatem的参数含义-程序员宅基地

文章浏览阅读250次。glm的旋转,平移、缩放OpenGlglm:rotate(旋转)glm:translate(平移)glm:scale(缩放)参考 总结GLM库中glm::transform(位移), glm:scale(缩放), glm::rotate(旋转)OpenGlglm:rotate(旋转)函数功能,将物体进行旋转,如下://目的:将物体 沿z轴 逆时针 旋转90度,创建其变换矩阵//1、初始..._opengl中的translatem的参数含义

移动APP性能测试指标_移动app 对请求的响应速度、移动端的等待时长 性能指标-程序员宅基地

文章浏览阅读2.1k次。性能测试在应用质量保证中起着重要的作用,概括为三个方面:应用在客户端性能的测试、应用在网络上性能的测试和应用在服务器端性能的测试。通常情况下,三方面有效、合理的结合,可以达到对系统性能全面的分析和瓶颈的预测。 通过性能测试工具得到测试对象的各项性能指标,将各项性能指标与行业中的标准值或者竞品值去做对比,以得到一个综合的结论与优化改进的方案。下面将以手游这样的典型APP为例对客户端性能指标进_移动app 对请求的响应速度、移动端的等待时长 性能指标

设计模式(十)——组合模式(Composite Pattern)_csdn 一个学院school由1到多个系department构成;每个系至少拥有1位指导教师ins-程序员宅基地

文章浏览阅读362次。组合模式(Composite Pattern)基本介绍组合模式(Composite Pattern),又叫部分整体模式,把部分和整体的关系用树形结构来表示,从而使客户端对单个对象和组合对象的访问具有一致性,可以使用统一的方式处理部分对象和整体对象。组合模式依据树形结构来组合对象,用来表示部分以及整体层次。UML原理类图角色及职责分析抽象构件(Component)角色: 定义了叶..._csdn 一个学院school由1到多个系department构成;每个系至少拥有1位指导教师instru