Ok,开始新的一章。基本的我就不写了,只写应该注意的地方和坑。代码基本都是来源于书上,少部分是我自己加上去的
- 重新开始(别误会,是函数)
> j <- function() {
if (!exists("a")) {
a <- 1
} else {
a <- a + 1
}
a
}
> j()
[1] 1
> j()
[1] 1
#因为每次调用这个函数都会创建一个新环境,函数不可能知道上次被调用时发生了什么,每次调用都是独立的
- 动态查找,这个地方可以用来使坏😈
> f <- function() x
> x <- 15
> f()
[1] 15
> x <- 20
> f()
[1] 20
#然而,这样函数就不是独立的了,可以使用codetools::findGlobals()查看一个函数额所有外界依赖关系
> f <- function() x + 1
> codetools::findGlobals(f)
[1] "+" "x"
#使用emptyenv()清空环境不现实,这样你连"+"都用不了了。所以这样别人就有可能使坏了
#比如:趁你不在,把"("的这个函数给改掉—有1/10的概率得到比输入值大1的数
> `(` <- function(e1) {
if (is.numeric(e1) && runif(1) < 0.1) {
e1 + 1
} else {
e1
}
}
> replicate(50, (1 + 2))
> replicate(50, (1 + 2))
[1] 3 3 3 3 3 3 3 3 3 3 3 3 3 4 4 4 3 3 3 3 3 3 3 4 3 3 3 3 4 3 3 3 3 3 3 3 3 3
[39] 3 3 3 3 3 3 4 3 3 3 4 3
#看看,是的吧。解决方法很简单
> rm("(")
> replicate(50, (1 + 2))
[1] 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3
[39] 3 3 3 3 3 3 3 3 3 3 3 3
#重归于好,哈哈哈。这里不是教人使坏,其实是警示大家在开始R会话之前,尽量清空之前对话的数据
> rm(list = ls())
- 习题
> f <- function(x) {
+ f <- function(x) {
+ f <- function(x) {
+ x ^ 2
+ }
+ f(x) + 1
+ }
+ f(x) * 2
+ }
> f(10)
#在脑子里过一下这个会得到什么结果
好吧,答案是202
#解答思路:最内层函数要向外找变量值10,f(x) +1 值就成了101,然后f(x)*2就是202
- 自定义中缀运算符及其优先级调整策略
> `%foo%` <- `+`
> 2 %foo% 4
[1] 6
> `%mul%` <- `*`
> 2 %foo% 4 %mul% 3
[1] 18
#默认优先级是从左到右的,调整优先级,加括号就行了
> 2 %foo% (4 %mul% 3)
[1] 14
- 中缀函数:一般都是函数在参数的前面,可以使用中缀函数把函数放到参数的中间。另外我们可以自定义并且利用`(tab键上面的那个) 引用预留的或自定义(非法)的函数
> `%mul%`(3,4)
[1] 12
x <- 10; y <- 5
x + y
#> [1] 15
`+`(x, y)
#> [1] 15
for (i in 1:2) print(i)
#> [1] 1
#> [1] 2
`for`(i, 1:2, print(i))
#> [1] 1
#> [1] 2
if (i == 1) print("yes!") else print("no.")
#> [1] "no."
`if`(i == 1, print("yes!"), print("no."))
#> [1] "no."
x[3]
#> [1] NA
`[`(x, 3)
#> [1] NA
{ print(1); print(2); print(3) }
#> [1] 1
#> [1] 2
#> [1] 3
`{`(print(1), print(2), print(3))
#> [1] 1
#> [1] 2
#> [1] 3
上面这个思想和apply结合可以自编函数来处理每个元素,实现想要的功能
> add <- function(x, y) x + y
> sapply(1:10, add, 3)
[1] 4 5 6 7 8 9 10 11 12 13
> sapply(1:5, `+`, 3)
[1] 4 5 6 7 8
> sapply(1:5, "+", 3)
[1] 4 5 6 7 8
> x <- list(1:3, 4:9, 10:12)
> sapply(x, "[", 2)
[1] 2 5 11
> sapply(x, function(x) x[2])
[1] 2 5 11
- 函数参数
#使用参数列表来传递函数参数
> args <- list(1:10, na.rm = TRUE)
> do.call(mean, args)
[1] 5.5
#等同于
> mean(1:10,na.rm = TRUE)
[1] 5.5
#默认参数
> f <- function(a = 1, b = 2) {
c(a, b)
}
> f()
#> [1] 1 2
#默认参数可以使用其它参数来求值
g <- function(a = 1, b = a * 2) {
c(a, b)
}
g()
#> [1] 1 2
g(10)
#> [1] 10 20
#默认参数甚至可以是隐藏在函数内部的变量(这并不推荐)
h <- function(a = 1, b = d) {
d <- (a + 1) ^ 2
c(a, b)
}
h()
#> [1] 1 4
h(10)
#> [1] 10 121
#像上面这种,默认参数需要很长的计算才能得到,通常建议使用missing()函数判断,有需要再计算。
#缺点:不阅读文档就不知道那个参数是必须的。可以把默认参数设置成NULL,is.null()去判断参数是否设置了
- 终止函数stop()
> a <- function(x){
for (i in 1:x){
print(i)
if (i == 3){
stop("Error:3 is an error number")
}
}
}
> a(4)
[1] 1
[1] 2
[1] 3
Error in a(4) : Error:3 is an error number
- 惰性求值,即只在使用函数参数时,对其求值;有时可以用来删除一个if语句
> f <- function(a,b){
+ print(a)
+ }
> f(2)
[1] 2
> f_1 <- function(a,b){
+ print(a)
+ print(b)
+ }
> f_1(8)
[1] 8
Error in print(b) : 缺少参数"b",也没有缺省值
************************************************************
> a <- NULL
> if (is.null(a)) stop("a is null")
错误: a is null
> !is.null(a) || stop("a is null")
错误: a is null
> is.null(a) || stop("a is null")
[1] TRUE
...参数:它可以传递一个函数的参数到另一个函数(可以利用这个特性修改已知函数的参数,而不必列出所有原函数的参数);当传递到函数的参数数量不能确定的时候,它必须被使用
#用来传参
> new_plot <- function(x,y,type = "s",...){
plot(x,y,...)
}
#参数个数不确定
> num <- function(...,sep = "_"){
+ paste(...,sep = sep)
+ }
> num(1,2,3)
[1] "1_2_3"
- 对函数的参数进行修改,不会改变参数的原始值
> f <- function(x) {
+ x$a <- 2
+ x
+ }
> x <- list(a = 1)
> f(x)
$a
[1] 2
> x$a
[1] 1
- invisible()函数详解
f1 <- function() 1
f2 <- function() invisible(1)
f1()
#> [1] 1
f2()
f1() == 1
#> [1] TRUE
f2() == 1
#> [1] TRUE
********************************************************
#可以使用括号,强制显示
(f2())
#> [1] 1
#最常用的隐藏返回值的函数应该是"<- "了,这样可以把一个值赋给多个变量
a <- b <- c <- d <- 2
网友评论