概述
声明:
1、 作者水平有限,不足之处请指正!
2、本文不定时持续更新!
说明:#代表注释,##代表运行结果。
R自定义函数
- 定义
- 调用
- 递归
- 全局变量和局部变量
- 参考文件
函数最大的优点是代码复用,模块化设计。也就是说如果这一段代码块需要在多处使用,就应将其写成一个函数,多次调用,有效的规避了代码的重复。并且在修改时只需要修改函数即可。在定义函数时,个人建议将一小段代码封装成一个函数,使得代码可读性更高,并且能够降低程序的复杂性。
定义
函数名 <- function(形参) 函数体
一个自定义R 函数由三个部分组成:
- 函数体body(),即要函数定义内部要执行的代码;
- formals(),即函数的形式参数表以及可能存在的缺省值;
- environment(),是函数定义时所处的环境,这会影响到参数表中缺省值与函数体中非局部变量的的查找。如果函数内没有嵌套函数,则环境一般是R全局环境,否则会有一个私有环境。
可以通过body(),formals(),environment()函数分别得到函数的三部分。
函数体是一个或多个表达式的组合,如果函数体中没有return()函数返回值,则默认返回最后一个表达式为返回值。假如你需要返回多个结果,则可以尝试用list列表的形式返回,之后再进行unlist等操作。
函数在R 语言中与其他普通数值型对象、字符型对象有相同的地位,这也就意味着函数可以拥有属性。
# 定义一个求和函数
mysum <- function(x,y){
x + y
}
# 或者
mysum <- function(x,y) x+y # 因为函数只有一个表达式,大括号可省略
mysum(1:2,3:6)
## [1] 4 6 6 8
# 如果调用函数的形参、实参对应关系保存在列表中,可以用函数do.call() 来表示函数调用
do.call(mysum,list(1:2,2:3))
## [1] 3 5
#得到函数组成
body(mysum)
##{
## x + y
##}
formals(mysum)
## $x
## $y
## [1] 1
environment(mysum)
## <environment: R_GlobalEnv>
由于R推崇的是向量化的编程,所以形参可以为向量。当x,y长度不相等时,会循环长度短的向量,进而求和。如果你定义的函数不支持向量化的实参,别担心,R语言提供了Vectorize函数解决这一问题。
g <- function(x){
if(abs(x) <= 1) {
y <- x^2
} else {
y <- 1
}
y
}
gv <- Vectorize(g)
gv(c(-2, -0.5, 0, 0.5, 1, 1.5))
## [1] 1.00 0.25 0.00 0.25 1.00 1.00
下面再简单定义一个绘图函数
myplot <- function(){
par(mfrow = c(1,2))
curve(sin(x),from = 0,to = 2*pi,col = "red")
curve(cos(x),from = 0,to = 2*pi,add = T,col = "steelblue")
curve(log(x),from = 0,to = 2)
}
myplot()
即使函数没有参数,也不能去掉括号引用函数。
windows系统下,Rstudio可以手动保存图片为PDF,方便调节图形尺寸,便于图形美观。
指定缺省值
函数定义时有缺省值的形式参数在调用时可以省略对应的实参,省略时取缺省值。
mysum <- function(x,y=1){
x + y
}
mysum(1:2)
## [1] 2 3
调用
- 前缀形式:如mysum(1:2)
- 中缀形式:如5-2,或者是’-’(5,2)。因为它不是合法的R函数名。
- 替换形式:对属性进行修改,如通过colnames()函数赋值修改数据框或矩阵等列名。
- 特殊形式:比如x[1],x[[1]],for,if,(),{}等,这些函数都可称为初等函数,用户是无法访问其三部分的。
x <- 1:2
`[`(x,1)
x[1] # 与上一条命令结果相同
## [1] 1
`[<-`(x,1,10) # 与x[1] <- 10有微小的差异
## [1] 10 2
递归
R递归实现斐波那契数列:
# 参考李东风书籍
fib1 <- function(n){
if(n == 0) return(0)
else if(n == 1) return(1)
else if(n >=2 ) {
Recall(n-1) + Recall(n-2) # Recall代表调用函数自身
}
}
for(i in 0:5) cat("i =", i, " x[i] =", fib1(i), "n")
## i = 0 x[i] = 0
## i = 1 x[i] = 1
## i = 2 x[i] = 1
## i = 3 x[i] = 2
## i = 4 x[i] = 3
## i = 5 x[i] = 5
全局变量和局部变量
R语言中的变量是指向R对象的引用,在较简单的函数定义中大体上可以将R 变量看成是对应的存储空间,这一点与一般的计算机语言是有区别的。
- 全局变量
在所有函数外定义的变量是全局变量。在命令行定义的所有变量都保存在工作空间(workspace)中。 - 局部变量
在函数内部使用赋值定义的变量是局部变量,即局部变量也只能在函数内部被访问。局部变量在函数运行结束后会消失。
# 定义函数fun1
fun1 <- function(){
x <- 123
print(x)
}
fun1()
## [1] 123
print(x)
## Error in print(x) : 找不到对象'x'
那么如果R工作空间中已经存在同名的变量,会不会有影响?
fun1 <- function(){
x <- 123
print(x)
}
fun1()
## [1] 123
x <- c(1,2,3)
print(x)
## [1] 1 2 3
从上述小例子中可以发现,在函数中定义x时会变成局部变量,这种规则在R中称为掩藏。也就是函数本身是另一个工作空间。
那么想在函数中修改R全局环境中的变量怎么办??
x <- c(1,2,3)
fun1 <- function(){
x <<- 123
print(x)
}
fun1()
## [1] 123
print(x)
## [1] 123
<<- 可以帮助我们实现这种需求。
## 侵权请联系删除!
参考文件
[1] 《R 语言教程》李东风著
最后
以上就是正直月亮为你收集整理的R自定义函数定义调用递归全局变量和局部变量参考文件的全部内容,希望文章能够帮你解决R自定义函数定义调用递归全局变量和局部变量参考文件所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复