高级编程--创建函数
在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 <- (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)。
作者:zhang-X,转载请注明原文链接
















