R语言

function()编写函数

2020-06-14  本文已影响0人  小贝学生信

之前在R语言入门--第四节(数据管理进阶)笔记的最后部分以两个例子简单学习了利用function()自定义编写函数的方法,这次专门再学习下。

自定义函数的目的主要是为了简化代码。有人曾说只要一段代码需要复制粘贴的次数超过两次(也就是说,同一段代码至少有 3 个副本),那么就应该考虑编写一个函数。

一、function编写步骤

1、为函数选择一个合适的名称

2、列举出 function 中所用的输入

3、将已经编写好的代码放在函数体中

例子

函数功能:将数据中心化为0~1区间

rescale01 <- function(x) {
rng <- range(x, na.rm = TRUE)
# 中间计算结果保存为命名变量是一种非常好的做法,因为这样可以让代码的意义更加清楚。
(x - rng[1]) / (rng[2] - rng[1])
}
rescale01(c(0, 5, 10))
df <- data.frame(
  a = rnorm(10),
  b = rnorm(10),
  c = rnorm(10),
  d = rnorm(10)
)
rescale01(df$a)

当函数复杂时,可利用#加入注释,便于他人或者将来自己的理解。此外也可创建分节标记,快捷键Ctrl+Shift+R,方便代码管理。

二、常见搭配--if条件语句

if (condition) {
  # 条件为真时执行的代码
} else {
  # 条件为假时执行的代码
}

注意点

在测试相等关系时,一定要小心, == 是向量化的,很容易输出多个值,即要先检查长度是否相同。或者推荐使用非向量化的identical() 函数。 identical() 非常严格,总是返回一个 TRUE 或者一个 FALSE ,并且不限制参数类型。

教材说不能用|&,但我看链接笔记里也确实用到了&结构,存疑!

compute <- function(x, y, op) {
switch(op,
 plus = x + y,
 minus = x - y,
 times = x * y,
 divide = x / y,
 stop("Unknown op!")
) 
}
compute(1, 2, "pus")

三、函数参数

1、参数分类

如前所述函数的参数通常分为两大类:一类提供需要进行计算的数据,另一类控制计算过程的细节。举例----

2、特殊的数据参数

?sum
sum(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
?stringr::str_c
stringr::str_c("a", "b", "c", "d", "e", "f")

3、设置默认细节调节参数

# 使用近似正态分布计算均值两端的置信区间
mean_ci <- function(x, conf = 0.95) {
  se <- sd(x) / sqrt(length(x))
  alpha <- 1 - conf
  mean(x) + se * qnorm(c(alpha / 2, 1 - alpha / 2))
}

x <- runif(100)
mean_ci(x)
mean_ci(x, conf = 0.99)

调用函数时,最好遵循参数的书写格式。即在其中 = 的两端都加一个空格。逗号后面应该总是加一个空格,逗号前面则不要加空格。此外值得注意的一点是我们经常省略数据参数的名称。

4、检查参数值

(1)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)
}
wt_mean(1:5,6:10)
(2)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)
}
wt_mean(1:6, 6:1, na.rm = "foo")

5、常见通用参数

将 na.rm 的默认值设为 FALSE 是情有可原的,因为缺失值有时是非常重要的。虽然代码中经常使用的是 na.rm = TRUE ,但是通过默认设置不声不响地忽略缺失值并不是一种良好的做法。

四、函数返回值

补充:管道符

mtcars$cyl %>%
  table() %>%
  barplot()

支持管道符的函数类型

show_missings <- function(df) {
  n <- sum(is.na(df))
  cat("Missing values: ", n, "\n", sep = "")
  invisible(df)
}
show_missings(mtcars)
library(dplyr)
mtcars %>%
  show_missings() %>%
  mutate(mpg = ifelse(mpg < 20, NA, mpg)) %>%
  show_missings()
上一篇下一篇

猜你喜欢

热点阅读