R 学习笔记:R 函数

R 中的许多对数据的处理需要用函数来完成, 要么使用别人编写好的函数, 要么使用自己去写的函数. 所以, 知道 R 语言中的函数是什么, 该怎么用是十分有必要的.

R 语言中的函数, 有的使用 R 语言去写的, 有的则考虑到性能等原因使用 C/C++ 等语言来写. 使用非 R 语言写的函数和 R 语言写的函数是有差别的. 下面主要考虑 R 语言编写的函数吧.


函数结构

一个 R 函数有三个部分: 函数体 (body); 参数 (formals); 环境 (environment). 对于一个函数, 可以使用 body(), formals(), environment() 等函数可以去查看函数的这些部分.

对象查找

函数中的对对象查找是有一定的顺序的. R 语言中的名称域查找有两类: 词法域 (lexical scoping), 默认查找的方式; 动态域 (dynamic scoping), 在交互式操作的运行中可以减少输入.

词法域 (lexical scoping) 查找有四个基本概念.

  • 名称覆盖 (name masking): 首先查找函数体内的对象是否有符合对应名称的变量, 如果没有的话, 就再上升一个层次继续查找.
  • 方程和变量 (functions v.s. variables): 如果方程和变量的名称一样的话, 会根据当时的语法去判断是否是方程或变量.
  • 起始 (a fresh start): 函数每次运行, 其中的变量都是重新建立的, 和上次运行没有关系.
  • 动态查找 (dynamic lookup): R 语言中, 对变量的查找是在函数运行的时候进行的, 而不是在建立的时候建立的.

参数解析

R 函数对于参数的解析是很方便的. R 函数的参数可以按照顺序进行分配, 也可以通过参数名称进行指定. 所有的参数会把直接通过参数名赋值的参数进行对应赋值, 然后剩下的没有通过参数名赋值的, 按照顺序排列, 通过按顺序赋值的方式进行赋值.

myfunc1 <- function(a, b, c) {
    print(a)
    print(b)
    print(c)
}
myfunc1(1, 2, b = 3)
#[1] 1
#[1] 3
#[1] 2

R 函数还可以指定默认值. 直接在参数表中加上等号来设置默认参数. 需要注意的是, 有默认值的参数也会按照顺序进行赋值, 并不会跳过有默认值的参数.

myfunc2 <- function(a, b = 3) {
    print(a)
    print(b)
}
myfunc2(1)
#[1] 1
#[1] 3

可以通过 missing() 函数来判断某个参数是否缺失.

myfunc3 <- function(a, b) {
    c(missing(a), missing(b))
}
myfunc3(b = 1)
#[1]  TRUE FALSE

另外只有用到的参数才会实际上解析, 没有用到的参数就不会解析, 这样也不会耗费时间. 如果强制对某个没有用到的参数进行解析, 可以使用 force 函数.

需要提及的是 ... 参数. 这个参数可以匹配任何没有被匹配的参数, 并可以方便地传递到其他函数. 但是这个参数并不会去验证正确性, 所以即是有打字错误, 外部函数并不会报错.

myfunc4 <- function(...) {
    names(list(...))
}
myfunc4(a = 1, b = 2)
#[1] "a" "b"

返回函数

如果没有使用 return 函数去指定函数的返回值, 则默认返回函数体中最后一条执行的命令的结果. 尽管函数只能返回一个结果, 但这个结果可以是一个数值, 可以是一个列表, 也可以是一个函数, 所以实际上一个函数可以返回符合需要的值.

如果不希望返回值被打印, 可以使用 invisable 函数. invisable 的结果可以被赋值, 但不会打印在屏幕, 不过总可以通过把其值包含在小括号中来打印出来.

(invisable(2))
#[1] 2
(a <- 2)
#[1] 2

on.exit 函数可以设置当一个函数结束时采取什么动作. 其中可以是改变工作区间, 也可以删除临时变量等.

特殊函数

R 语言中有两类特殊函数: 中置函数 (infix function), 替换函数 (replacement function).

中置函数

经常用到的很多函数都是前置的, 就是一个函数名, 然后后面是括号和括号里面的参数. 有一些函数是中置的. R 中内部定义了一些: ::, $, @, ˆ, *, /, +, -, >, >=, <, <=, ==, !=, !, &, &&, |, ||, ~, <-, <<-. 自己定义的中置函数需要在前后加上百分号, 如一些已经定义好的函数: %%, %*%, %/%, %in%, %o%, %x%. 这些中置函数也可以像前置函数那样使用, 不过需使用引号来标明函数名.

"%+%" <- function(a, b) paste(a, b, sep = "")
"new" %+% "string"
#[1] "newstring"
`%+%`("new", " string")
#[1] "newstring"

替换函数

替换函数有着特殊的名称形式 xxx<-, 可以直接对内容进行替换. 常见的如 dim, names 等函数. 替换函数, 看上去是对变量内容的直接替换, 实际上在 R 里面是新建了一个变量, 所以效率依然是不高的.

"myfunc5<-" <- function(x, value) {
    x[2] <- value
    x
    }
x <- 1:5
myfunc5(x) <- 10
x
#[1]  1 10  3  4  5
By @Wolfson Liu in
Tags : #r,