跳至主要内容

R 函数使用教程

了解什么是 R 函数、R 中的函数类型,以及如何在 R 中创建您自己的函数。
· 11分钟 阅读

使用 AI 探索

如果您正考虑开启数据科学职业生涯,越早开始编码越好。无论您选择哪种编程语言作为起点,学习过程中您终将会与“函数”相遇。

函数是几乎所有现代编程语言的核心概念,包括数据科学中常见的编程语言,如Python、Julia,以及当然还有R。

在本教程中,我们将探讨 R 函数是什么以及如何使用它们。通过介绍 R 中函数的用途、语法与类型,您将获得掌握这一关键编程概念所需的一切。此外,您还将初步接触到创建函数的技巧。

R 中的函数是什么?

在编程中,函数是一组为执行特定任务而组织在一起的指令。函数背后的理念是创建可在需要时才被调用的自包含程序。

借助函数,程序员无需从零开始编写程序,从而避免重复,提高代码的健壮性与可读性。因此,作为经验法则,当您预计某段指令在代码中会被运行两次以上时,最好将其封装为函数。

函数用途广泛、形式多样。一般来说,绝大多数函数会接收输入数据、对其进行处理,并返回结果。函数所操作的数据由所谓的参数(arguments)指定,参数也可用于控制或改变函数执行任务的方式。

根据函数的来源,我们可以将 R 中的函数大致分为三类:

  • 内置函数
  • R 包中的函数
  • 用户自定义函数(UDF)

接下来,我们将解释 R 中不同类型函数的特点。

R 的内置函数

R 是一种功能强大的编程语言,自带大量可随时调用的内置函数。作为一门偏重数学的语言,R 内置了许多用于执行数值运算的函数。以下是一些常用示例:

  • print()。在 R 控制台显示一个 R 对象
  • min(), max()。计算数值向量的最小值与最大值
  • sum()。计算数值向量的总和
  • mean()。计算数值向量的均值
  • range()。计算数值向量的最小值与最大值
  • str()。显示 R 对象的结构
  • ncol()。返回矩阵或数据框的列数
  • length()。返回 R 对象(如向量、列表、矩阵)的元素数量。

在下面的代码中,您可以看到使用这些函数从一个向量计算统计量是多么简单:

>>> v <- c(1, 3, 0.2, 1.5, 1.7)
>>> print(v)
[1] 1.0 3.0 0.2 1.5 1.7
>>> sum(v)
[1] 7.4
>>> mean(v)
[1] 1.48
>>> length(v)
[1] 5

您可以在我们全面的 R 技能路径中学习 R 函数与更多内容,帮助您像程序员一样编写代码。

R 包中的函数

尽管内置函数数量众多且类型丰富,但它们仍不足以完成在 R 中可以做的各种酷炫工作,从绘制引人注目的数据可视化到训练强大的机器学习模型。

执行这些任务的绝大多数函数都存在于外部包或库中。包是以良好定义的格式打包的 R 函数、数据与编译代码的集合,用于增加特定功能。大多数包可免费使用,并可在常用的包仓库中找到,如 CRAN,目前上面有近 20,000 个贡献包。

要使用包中的函数,首先需要安装该包。例如,如果您想安装 stringr(一个用于处理正则表达式的流行包),可以使用以下语句:

install.packages('stringr')

安装完成后,要将其加载到 R 环境中,使用 library 语句:

library(stringr)

现在,您就可以使用 stringr 包中所有可用的函数了。例如,试试 str_detect() 函数:对于字符串中匹配模式的每个元素返回 TRUE,否则返回 FALSE。

str_detect('DataCamp', "Data")
[1] TRUE

如果您想进一步了解 R 包及其用法,请查看这篇 DataCamp 的R 包教程。

用户自定义函数

理解 R 中函数工作方式的最佳方法就是创建您自己的函数。所谓用户自定义函数(UDF)由程序员设计,用于执行特定任务。

R 函数通常采用以下语法:

function_name <- function(argument_1, argument_2) { 
  function body
  return (output)
}

我们可以区分四个主要要素:

  • 函数名。要创建 UDF,首先需要为其指定名称并将其保存为一个新对象。之后只需在需要使用时调用该名称即可。
  • 参数。函数参数(也称为形参)在圆括号内提供。参数对于让函数知道应接收哪些数据作为输入和/或如何调整函数行为至关重要。
  • 函数体。花括号内是函数体,即基于参数提供的信息来解决特定任务的指令。
  • 返回语句。如果您希望函数将函数体运算得到的结果保存为变量,则需要包含 return 语句。

例如,如果您想创建一个计算两个数均值的函数:

mean_two_numbers <- function(num_1, num_2) {
  mean <- (num_1 + num_2) / 2
  return (mean)
}

现在,如果您要计算 10 和 20 的均值,只需如下调用函数:

>>> mean_two_numbers(10,20)
[1] 15

R 函数中的参数类型

参数是每个函数中的关键元素。尽管理论上可以编写没有参数的函数(见下例),但大多数函数都有参数。这很合理,因为参数告诉函数应接收哪些数据作为输入。同样,如果我们希望函数以多种方式执行任务,也可以通过参数来实现。

hello <- function() {
  print('hello, my friend')
}
>>> hello()
[1] "hello, my friend"

R 函数中的参数数量没有上限;您可以在括号中用逗号分隔添加它们。一般而言,参数越多,函数通常越复杂。

创建带参数的函数后,每次使用它时都需要为不同参数提供取值;否则,R 会抛出错误。例如,如果您未提供用于计算均值的两个数的值,我们的函数将无法工作。

不过,您可以在定义函数时使用默认参数来避免该错误。默认参数在您调用函数但未提供该参数时提供一个默认值。回到之前的两个数求均值的函数,这次我们为第二个数添加一个默认参数。

mean_two_numbers <- function(num_1, num_2 = 30) {
  mean <- (num_1 + num_2) / 2
  return (mean)
}

如果现在在调用函数时未提供 num_2 参数的值,R 会自动采用默认值(即 30):

>>> mean_two_numbers(num_1 = 10)
[1] 20

理解 R 函数的返回值

函数通常接收一些数据作为输入,并输出一个结果。在某些编程语言中,若要将函数结果保存为变量,您需要在函数体末尾显式加入 return 语句。否则,函数只会显示一个仅存在于变量作用域内的值。

R 并非如此,R 总会返回一个可存入变量的值。不过,为了代码的可读性,在定义函数时加入 return 语句仍然是很好的实践。

mean_two_numbers <- function(num_1, num_2) {
  # Function with return 
  mean <- (num_1 + num_2) / 2
  return (mean)
}
mean_two_numbers_2 <- function(num_1, num_2) {
  # Function without return
  mean <- (num_1 + num_2) / 2
  mean
}
> mean_two_numbers(10,50)
[1] 30
 > mean_two_numbers_2(10,50)
[1] 30

最后,如果您希望函数返回多个值,需要将不同结果存入列表,并将其包含在返回语句中:

mean_sum <- function(num_1, num_2) {
  mean <- (num_1 + num_2) / 2
  sum <- num_1 + num_2
  return (list(mean, sum))
}
>>> mean_sum (10, 20)
[[1]]
[1] 15
[[2]]
[1] 30

在 R 中调用函数

在前面的部分中,我们已经看到多个调用函数的示例。不过,有必要澄清当我们传递参数时,R 在底层是如何工作的。

R 支持两种传参方式:按位置与按名称。如果采用第一种方式,我们需要按照函数定义中参数的顺序依次写出取值。

如果按名称传参,我们需要显式指定参数名及其对应的值。由于参数与值已一一对应,顺序无关紧要。

最后,也可以混合使用两种策略。在这种情况下,具名参数会先从参数列表中提取并优先匹配,其余参数再按位置匹配。

hello <- function(name, surname) {
  print(paste('Hello', name, surname))
}
# Calling arguments by position
> hello('Greta','Thunberg')
[1] "Hello, Greta Thunberg"
# Calling arguments by name
> hello(surname='Thunberg', name='Greta')
[1] "Hello, Greta Thunberg"
# Calling arguments by position and by name
> hello(surname='Thunberg', 'Greta')
[1] "Hello, Greta Thunberg"

为 R 函数编写文档

创建函数时,一个良好实践是为其提供使用文档,特别是当函数较复杂时。非正式的方式是在函数体内添加注释。您也可以通过在无参数的情况下调用函数来查看这些文档:

hello <- function(name, surname) {
  # Say hello to a person with name and surname
  print(paste('Hello', name, surname))
}
>>> hello
function(name, surname) {
  # Say hello to a person with name and surname
  print(paste('Hello,', name, surname))

然而,如果您的函数属于更大的包并希望为其编写文档,您应在单独的 .Rd 文档中撰写正式文档。您可以在查看某个函数的帮助文件时看到这类文档的效果,例如 ?mean。

结语

您已经读到了本教程的最后,恭喜!与许多其他语言一样,函数在 R 中至关重要。无论是内置函数、外部包中的函数,还是由您亲自创建的函数,掌握函数都是您编程之路上的重要里程碑。如果您想继续提升自己在 R 中使用函数的能力,请查看以下资源!

主题