07

函数

自定义函数与控制流

基础篇

上一节课我们认识了向量操作符,体会到了向量化操作的强大,事实上,向量操作符是一种函数。R 语言的强大就在于它拥有丰富的函数,这里的函数和我们高中数学中的函数 y = f(x) 没什么区别。

基础函数

R 语言内置了很多统计函数,比如对于向量x

R
x <- c(2, 7, 8, 9, 3)

打印向量x

R
print(x)

求开方

R
sqrt(x)

求自然对数

R
log(x)

求向量元素之和

R
sum(x)

求向量元素的均值

R
mean(x)

求向量元素的标准差

R
sd(x)

找出向量元素中的最小值

R
min(x)

找出向量元素中的最大值

R
max(x)

计算向量元素的个数

R
length(x)

对向量元素大小排序

R
sort(x)

找出向量元素的唯一值,就是给出去重后的数据

R
a <- c("a", "b", "b", "c", "d", "a", "g", "c", "d")
unique(a)

给出向量的分位数

R
quantile(x)

判断是否为数值型/字符串型

R
is.numeric(x)
is.character(x)

转化成字符串型

R
as.character(x)
# as.logical(x)
# as.numeric(x)

判断向量元素是否大于5

R
x <- c(2, 7, 8, 9, 3)
x &gt; 5
R
ifelse(x &gt; 5, "big", "small")

向量的函数

用在向量上的函数,可以分为向量化函数(vectorized function)和汇总类函数(summary function),

图片

当然,也会有例外,比如unique()函数,它返回的向量通常不会与输入的向量等长,既不属于向量化函数,也不属于汇总类函数。

课堂练习

  • 向量x <- c(2, 7, 8, 9, 3)的平方,加上5
R
x <- c(2, 7, 8, 9, 3)
x^2 + 5
  • 向量的元素减去其均值
R
x <- c(2, 7, 8, 9, 3)
x - mean(x)
  • 向量标准化(向量减去其均值之后,除以标准差)
R
x <- c(2, 7, 8, 9, 3)
(x - mean(x)) / sd(x)
  • 如果想对更多的向量,也做标准化处理呢?
R
y <- c(1, 5, 7, 8, 9, 3)
(y - mean(y)) / sd(y)
R
z <- c(4, 7, 7, 8, 9, 3, 9, 6)
(z - mean(z)) / sd(z)

简单重复比较累,有没有一劳永逸的方法?

自定义函数

R
my_std <- function(x) {
   (x - mean(x)) / sd(x)
 }
R
my_std(x)
my_std(y)
my_std(z)

::: {.rmdnote} 现在my_std 是一个糖葫芦瘦身机器了,放进一个胖瘦不匀称的糖葫芦,出来一个身材匀称的糖葫芦。 :::

R
my_std <- function(x) {
   ...
}
  • 创建,由function(...)创建一个函数
  • 参数,由(...) 里指定参数,比如function(x)中的参数为 x
  • 函数主体,一般情况下,在function(...)后跟随一对大括号{ },在大括号里声明具体函数功能,在代码最后一行,可以用return返回计算后的值。当然,如果函数的目的只是返回最后一行代码计算的值,这个return可以省略。
  • 函数名,function() { } 赋值给新对象,比如这里的my_std,相当于给函数取一名字,方便以后使用。
  • 函数调用,现在这个函数名字叫my_std,需要用这个函数的时候,就调用它的名字my_std()
R
my_std(x = c(1, 5, 7, 8, 9, 3)) # 或者
my_std(c(1, 5, 7, 8, 9, 3))     # 或者

input <- c(1, 5, 7, 8, 9, 3)
my_std(input)

课堂练习

  • 根据下面的数学表达式,写出函数

$$ \mathrm{rescale}(x) = \frac{x_i- min(x)}{max(x) - min(x)} $$

使用宏包的函数

安装宏包与使用宏包

安装宏包 install.packages("dplyr") 相当于你买了一台电视机,安装一次就够了; 加载 library("dplyr")相当于你每次要看电视,就需要插上电、打开电视的动作,运行library("dplyr")才能用里面的函数。

示意图

各种宏包也为我们准备了不同的函数,我们在使用前一般会先加载该宏包,比如后面章节我们会用的dplyr宏包中的select()函数,它用于选取数据框的某列

R
library(dplyr)

select(starwars, height)

指定函数的所属宏包

但是,其它宏包可能也有select()函数,比如MASSskimr,如果同时加载了dplyrMASSskimr三个宏包,在程序中使用select()函数,就会造成混淆和报错。这个时候就需要给每个函数指定是来源哪个宏包,具体方法就是在宏包和函数之间添加::,比如dplyr::select()skimr::select() 或者MASS::select()

至此,我们接触到了三类函数

  • 内置的函数
  • 自定义的函数
  • 宏包的函数

如何获取帮助

  • 记住和学习所有的函数几乎是不可能的
  • 打开函数的帮助页面(Rstudio右下面板的Help选项卡)
R
?sqrt
?gather
?spread
?ggplot2
?scale
?map_dfr

比如:

图片

习题

  • 根据方差的数学表达式,写出方差的计算函数,并与基础函数var()的结果对比

$$ \mathrm{Var}(x) = \frac{1}{n - 1} \sum_{i=1}^n (x_i - \bar{x}) ^2 $$

  • 自定义函数,它的作用是将输入的身高height(cm)与体重weight(kg)计算之后的BMI结果返回,BMI的计算公式为:

$$ \mathrm{BMI} = \frac{weight(kg)}{height(m)^2} $$

R
get_bmi <- function(height, weight) {
  # ...
}
get_bmi(175, 65)
  • 对于给定的向量 vector和阈值threshold,求出vector中所有大于该阈值的元素的均值
R
mean_above_threshod <- function(vector, threshold) {
  
}

阅读

  • 推荐您阅读(https://r4ds.had.co.nz/functions.html)