小洁详解《R数据科学》--第十四章 函数
2018-11-06 本文已影响12人
小洁忘了怎么分身
终于学到了写函数,省时省力呀。
1.居然没有准备工作。
2.使用函数的情况:同样的数据需要多次重复
先理解一下range函数:输入一个向量,返回其最小值和最大值。
y <- range(c(1,3,-1))
y #最小值和最大值
#> [1] -1 3
y[1] #最小值
#> [1] -1
写成函数
rescale01 <- function(x) {
rng <- range(x, na.rm = TRUE)
(x - rng[1]) / (rng[2] - rng[1])
}
rescale01(c(0, 5, 10))
#> [1] 0.0 0.5 1.0
我写了一个更简单的函数帮助理解
doodle <- function(x){
range(x)-3
}
doodle(c(1, 2, 3, NA, 5))
#> [1] NA NA
创建函数的关键步骤:命名、参数、函数体
3.函数命名
函数名是动词,参数名是名词。
多个单词组成的函数名用snake_case命名法。即用下划线连接。
一族函数,可以加通用前缀。
4.条件执行
(1)condition
模板
if (condition) {
} else {
}
i=8
if(i<5){
"doudou"
}else{
"huahua"
}
#> [1] "huahua"
condition是逻辑值。
补充操作:ifelse(test,yes,no)
x <- c(3,4,6)
ifelse(x>5,x+3,x-3)
#> [1] 0 1 9
整数和双精度浮点数
- 先看类型
class(0L)
#> [1] "integer"
class(0)
#> [1] "numeric"
- 判断是否相等
sqrt(2) ^ 2==2
#> [1] FALSE
identical(sqrt(2) ^ 2,2)
#> [1] FALSE
- 解决办法
dplyr::near(sqrt(2) ^ 2,2)
#> [1] TRUE
(2)多重条件
入门操作
if (this) {
} else if (that) {
} else {
}
升级操作:switch
biu <- function(x, y, op) {
switch(op,
plus = x + y,
minus = x - y,
times = x * y,
divide = x / y,
stop("Unknown op!")
)
}
x <- biu(3,5,"divide")
#此处注意这三个输入参数分别是两个数字和一个运算方式。如果是三个数字则计算结果为NULL
升级操作:cut
按照坐标划分区间。
temp <- seq(-10, 50, by = 5)
cut(temp, c(-Inf, 0, 10, 20, 30, Inf), right = TRUE,
labels = c("freezing", "cold", "cool", "warm", "hot"))
#> [1] freezing freezing freezing cold cold cool cool
#> [8] warm warm hot hot hot hot
#> Levels: freezing cold cool warm hot
#right:logical, indicating if the intervals should be closed on the right (and open on the left) or vice versa.
查看cut的帮助文档得知,参数right=TRUE表示左开右闭,right=FALSE表示左闭右开。
(3)代码风格
代码短则可以不用大括号,一行写开。(不推荐)
大括号内的内容缩进。
大括号单独占一行或跟else。
5.函数参数
函数的参数分数据和细节两类。细节参数有默认值。
加空格:符号前后。注意逗号只在后面加,不在前面加。
(1)选择参数名称
(2)检查参数值
生成报错:
stop
wt_mean <- function(x, w) {
if (length(x) != length(w)) {
stop("`x` and `w` must be the same length", call. = FALSE)
}
sum(w * x) / sum(x)
}
stopifnot
wt_mean <- function(x, w, na.rm = FALSE) {
stopifnot(is.logical(na.rm), length(na.rm) == 1)
stopifnot(length(x) == length(w))
if (na.rm) {
miss <- is.na(x) | is.na(w)
x <- x[!miss]
w <- w[!miss]
}
sum(w * x) / sum(x)
}
(3)点点点(...)
作用:接受任意数量的输入
6.返回值
(1)提前返回--return
简单的情况写在if,复杂的写在else。
好用的思路:if(!x)
(2)支持管道操作
支持管道操作的函数:
转换函数--计算
副作用函数--执行某种行为,比如绘图、保存。
7.环境
R会在定义函数的环境中寻找没有定义的变量。
可以编写函数覆盖默认的函数。(好像暂时用不到)