高级编程--创建函数(函数语法、对象范围、环境)

高级编程--创建函数

R中处处是函数。算数运算符+-/*实际上也是函数。例如,2 + 2等价于 "+"(2, 2)

1. 函数语法

函数的语法格式是:

functionname <- function(parameters){

 statements

 return(value)

}

如果函数中有多个参数,那么参数之间用逗号隔开。

参数可以通过关键字和/或位置来传递。另外,参数可以有默认值。请看下面的函数:

f <- function(x, y, z=1){

  result <- x + (2*y) + (3*z)

  return(result)

}

 

f(2,3,4)    #通过位置传递

 

f(2,3)    #通过位置传递

 

f(x=2, y=3)     #通过关键字传递

 

f(z=4, y=2, 3)    #y和z是通过关键字传递的

 

可以使用args()函数来观测参数的名字和默认值:

args(f)

 

args()被设计用于交互式观测。如果你需要以编程方式获取参数名称和默认值,可以使用formals()函数。它返回含有必要信息的列表。

参数是按值传递的,而不是按地址传递。请看下面这个函数语句:

result <- lm(height ~ weight, data=women)

result

 

2. 对象范围

在典型情况下,有如下几点:

1)在函数之外创建的对象是全局的(也适用于函数内部)。在函数之内创建的对象是局部的(仅仅适用于函数内部)。

2)局部对象在函数执行后被丢弃。只有那些通过return()函数(或使用算子<<-分配)传回的对象在函数执行之后可以继续使用。

3)全局对象在函数之内可被访问(可读)但是不会改变(除非使用<<-算子)。

4)对象可以通过参数传递到函数中,但是不会被函数改变。传递的是对象的副本而不是变量本身。

x <- 2

y <- 3

z <- 4

f <- function(w){

  z <- 2

  x <- w*y*z

  return(x)

}

f(x)

 

x

 

结果分析:在这个例子中,x的一个副本被传递到函数f()中,但是初始的x不变。y的值通过环境得到。尽管z存在于环境中,但是在函数中设置的值被使用并不改变在环境中的值。

 

3  环境

R中,环境包括框架和外壳。框架是符号-值(对象名称及其内容)的集合,外壳是指向封闭环境的一个指针。封闭环境也称为父环境。R允许人们在语言内部操作环境,以便达到对范围的细微控制以及函数和数据的分离。

在互动部分,当你第一次看到R的提示时,你处于全局环境。你可以通过new.env()函数创建一个新的环境并通过assign()函数在环境中创建任务。对象的值可以通过get()函数从环境 中得到。这里有一个例子:

x <- 5

myenv <- new.env()

assign("x", "Homer", env=myenv)

ls()

 

 ls(myenv)

 

x

 

 get("x", env=myenv)

 

结果分析:在全局环境中存在一个称为x的对象,其值为5。一个称为x的对象还存在于myenv的环境中,其为"Homer"

另外使用assign()get()函数时可以使用$符号。例如:

myenv <- new.env()

myenv$x <- "Homer"

myenv$x

 

parent.env()函数展示了父环境。继续这个例子,myenv的父环境就是全局环境:

parent.env(myenv)

 

全局环境的父环境是空环境。

因为函数是对象,所以它们也有环境。这在探讨函数闭包(function closure,以创建时状态被打包的函数)时非常重要 。请看由另一个函数创建的函数:

trim <- function(p){

  trimit <- function(x){

    n <- length(x)

    lo <- floor(n*p) + 1

    hi <- n + 1 - lo

    x <- sort.int(x, partial = unique(c(lo, hi)))[lo:hi]

  }

  trimit

}

trim(p)函数返回一个函数,即从矢量中修剪掉高低值的p%

x <- 1:10

trim10pct <- trim(.1)

y <- trim10pct(x)

y

 

trim20pct <- trim(.2)

y <- trim20pct(x)

y

 

这样做是因为p值在trimit()函数的环境中并被保存在函数中:

ls(environment(trim10pct))

 

get("p", env=environment(trim10pct))

 

一般情况下,对象的值是从本地环境中获得的。如果未在局部环境中找到对象,R会在父环境中搜索,然后是父环境的父环境,直到对象被发现。如果R搜索到空环境仍未搜索到对象,它会抛出一个错误。我们把它称为词法域(lexical scoping)。

posted @ 2021-08-17 21:10  zhang-X  阅读(479)  评论(0)    收藏  举报