函数
大多数的变量类型仅用于存储数据,而函数能让我们和数据一起工作,它们是动词,而非名词
和环境类似,它们只是另一种数据类型,可以分配、操纵,甚至将它传递给其它函数的数据类型
创建和调用函数
键入一个函数的名称,将显示其运行的代码
rt
## function(n, df, ncp)
## {
## if(missing(ncp))
## .External(C_rt, n, df)
## else rnorm(n, ncp)/sqrt(rchisq(n, df)/df)
## }
## <bytecode: 0x0000000019738e10>
## <environment: namespace:stats>
rt函数需要输入3个参数 n df 和ncp,都是形式参数(formal arhument)
当调用函数并给它们递值时,这些值被称为参数
参数和形式参数间的差异不是很重要
在大括号之间,可以看到函数体内代码行,它们就是每次调用rt时要执行的代码
这里有非显式的return关键字声明应该从函数返回值
在R中,函数中计算的最后一个值将自动返回
创建函数
hypotenuse <- function(x, y)
{
sqrt(x ^ 2 + y ^ 2)
}
# 函数体只有一行代码,可以省略大括号
hypotenuse <- function(x, y) sqrt( x ^ 2 + y ^ 2)
可以使用以下任意一种方式来调用这个函数
hypotenuse(3, 4)
## [1] 5
hypotenuse(y = 24, x = 7)
## [1] 25
调用函数时,如果不命名参数,则按位置匹配它们
可传入命名参数来改变传递参数的顺序
可以给函数提供默认值
hypotenuse <- function(x = 5, y = 12)
{
sqrt(x ^ 2 + y ^2)
}
hypotenuse() # 和hypotenuse(5, 12)相等
## [1] 13
formals
函数,取得函数的参数并返回一个(结对)列表
args
函数也能做相同的事,看上去更可读但编程风格不太友好
formaArgs
函数将返回参数名称的字符向量
formals(hypotenuse)
## $x
## [1] 5
##
## $y
## [1] 12
args(hypotenuse)
## function(x=5, y=12)
## NULL
formalArgs(hypotenuse)
## [1] "x" "y"
body
函数 返回函数体,好像不太有用的样子
deparse
函数 以文本方式检查函数体,例如要查找调用了另一函数的函数
(body_of_hypothenuse) <- body(hypotenuse))
## {
## sqrt(x^2 + y^2)
## }
deparse(body_of_hypotenuse)
## [1] "{" "sqrt(x^2 + y^2)" "}"
函数形参的默认值不仅仅事常数值,还可以把任何R代码放进去,甚至使用其它形参
下面的normalize函数将缩放一个向量,默认情况下,参数m和s是第一个参数的平均值和标准偏差,所以返回的向量将包含均值0和标准偏差1
normalize <- function(x, m = mean(x), s = sd(x))
{
(x-m)/s
}
normalized <- normalize(c(1, 3, 6, 10, 15))
mean(normalize) # 几乎是0
## [1] -5.537e-18
sd(normalized)
## [1] 1
# 不过,当x的某些元素没有给出时,normalize函数会有点小问题
normalize(c(1, 3, 6, 10, NA))
## [1] NA NA NA NA NA
如果向量的所有元素都没有给出,那么在默认情况下,mean和sd都将返回NA,因此,normalize函数的返回值中的所有元素都是NA值
如果有这样的选项:只有输入值是NA时才返回NA,那可能更高
mean和sd都有一个参数na.rm,它能让我们删除计算之前的任何缺失值
为了避免所有的NA值,可以在normalize中包含这个参数
normalize <- function(x, m=mean(na.rm=na.rm), s=sd(na.rm=na.rm), na.rm=FALSE)
{
(x-m)/s
}
normalize(c(1, 3, 6, 10, NA))
## NA NA NA NA NA
normalize(c(1, 3, 6, 10, NA), na.rm = T)
## [1] -1.0215 -0.5108 0.2554 1.2769 NA
为了避免输入那些实际上没有被函数用到的参数名(na.rm只被传递到mean和sd中),R提供了一个特殊的参数...
,它包含了所有不能被位置或名称匹配的参数
normalize <- function(x, m=mean(x, ...), s=sd(x, ...), ...)
{
(x-m)/s
}
normalize(c(1, 3, 6, 10, NA))
## [1] NA NA NA NA NA
normalize(c(1, 3, 6, 10, NA), na.rm=T)
## [1] -1.0215 -0.5108 0.2554 1.2768 NA
现在,在normalize(c(1, 3, 6, 10, NA), na.rm=T)
的调用中,参数na.rm并不能匹配normalize的任何形参,因为它不是x m或s
这意味着它被存储在normalize的参数…中
现在评估m的话,表达式mean(x, …)现在为mean(x, na.rm=TRUE)