R学习:环境和函数
R语言学习贴往期回顾
今天我们了解一下环境和函数
环境和函数
阅读本章后, 你会了解以下内容: · 环境是什么, 如何创建它; · 如何创建、 访问和列出环境内的变量; · 函数的各个组成部分; · 编写自己的函数; · 变量的作用域。
环境的创建是使用 new.env 函数:
an_environment<-new.env()
向环境中分配变量的方式与列表完全相同。可以使用双方括号或美元符号运算符。和列表一样, 环境变量的类型和大小可以不同
an_environment<-new.env()
an_environment[["pythag"]]<-c(12, 15, 20, 21)
an_environment$root<-polyroot(c(6, -5, 1))
assign 函数可以指定变量的存储位置
assign(
"moonday",
weekdays(as.Date("1969/07/20")),
an_environment
)
检索变量的方式也是如此:可以使用列表的索引语法,或 assign 的对立函数 get:
an_environment[["pythag"]]
## [1] 12 15 20 21
an_environment$root
## [1] 2+0i 3-0i
get("moonday", an_environment)
## [1] "星期日"
可以把环境参数传入 ls 和 ls.str 函数中, 列出它的所有内容
ls(envir = an_environment)
## [1] "moonday" "pythag" "root"
ls.str(envir = an_environment)
## moonday: chr "Sunday"
## pythag: num [1:4] 12 15 20 21
## root: cplx [1:2] 2+0i 3-0i
可用 exists 函数测试变量是否在环境中:
exists("pythag", an_environment)
## [1] TRUE
使用 as.list 和 as. environment 函数能分别实现从环境到列表或相反过程的转换。在后一种情况中, 还可以使用 list2env 函数, 它在创建环境时更为灵活:
# 转换为列表
(a_list<-as.list(an_environment))
## $pythag
## [1] 12 15 20 21
##
## $moonday
## [1] "Sunday"
##
## $root
## [1] 2+0i 3-0i
# 再转换回来。以下两行代码的效果一样。
as.environment(a_list)
## <environment: 0x000000004a6fe290>
list2env(a_list)
## <environment: 0x000000004ad10288>
函数
大多数的变量类型仅用于存储数据, 而函数能够让我们和数据一起工作, 它们是“动词”而非“名词”。和环境类似, 它们只是另一种数据类型, 我们可以分配、 操纵, 甚至将它传递给其他函数的数据类型。
创建和调用函数
键入一个函数的名称,将显示其运行的代码。以下是 rt 函数, 该函数将生成基于 T 分布的随机数
rt
## function (n, df, ncp)
## {
## if (missing(ncp))
## .External(C_rt, n, df)
## else rnorm(n, ncp)/sqrt(rchisq(n, df)/df)
## }
## <bytecode: 0x0000000019738e10>
## <environment: namespace:stats>
rt 需要三个输入参数:n 是要产生的随机数的数目, df 是自由度值, ncp 是一个可选的非中心参数。从技术上来说, 三个参数 n、 df 和 ncp 是 rt 函数的形式参数(formal argument)。当你调用该函数并给它传递值时, 这些值被称为参数。
在大括号之间, 你可以看到函数体内代码行。它们就是每次调用 rt 时要执行的代码
在 R 中, 函数中计算的最后一个值将自动返回。以 rt 为例, 如果 ncp 参数被省略,将会调用C 代码生成随机数并返回。否则,该函数会调用 rnorm、 rchisq 和 sqrt 函数计算并返回值。
要创建我们自己的函数,只需像其他任何变量一样为它赋值。举一个例子, 创建一个函数来计算直角三角形斜边的长度
hypotenuse <- function(x, y)
{
sqrt(x ^ 2 + y ^ 2)
}
这里, hypotenuse 是我们正在创建的函数, x 和 y 是它的参数(形参), 在大括号中的内容是函数体
现在, 可以使用以下任意一种方式来调用这个函数:
hypotenuse(3, 4)
## [1] 5
hypotenuse(y = 24, x = 7)
## [1] 25
当我们调用函数时, 如果不命名参数, 则 R 将按位置匹配它们。以 hypotenuse(3, 4) 为例:3 是第一个参数, 因此它对应 x;4 是第二个参数, 因此它对应 y。
在
以下新版本的代码中, 如果我们不给函数传递任何值, 则 x 会取默认值 5, 而 y 会取 12:
hypotenuse <- function(x = 5, y = 12)
{
sqrt(x ^ 2 + y ^ 2)
} h
hypotenuse() # 与 hypotenuse(5, 12) 相等
向其他函数传递和接收函数
函数可以像其他变量类型一样地使用,我们可将之作为其他函数的参数, 并且从函数中返回。一个常见的, 把其他函数当成参数的例子是 do.call。此函数提供了一种调用其他函数的替代语法,让我们可以像列表一样传递参数, 而不是逐次传递:
do.call(hypotenuse, list(x = 3, y = 4))
# 和 hypotenuse(3, 4) 一样
## [1] 5
常见的案例为 do.call 与 rbind 混用。你可以结合这两个函数, 你可以一次拼接多个数据框或矩阵:
dfr1 <- data.frame(x = 1:5, y = rt(5, 1))
dfr2 <- data.frame(x = 6:10, y = rf(5, 1, 1))
dfr3 <- data.frame(x = 11:15, y = rbeta(5, 1, 1))
do.call(rbind, list(dfr1, dfr2, dfr3)) # 和 rbind(dfr1, dfr2, dfr3) 一样
我们还可以以匿名方式传递函数 :
x_plus_y <- function(x, y) x + y
do.call(x_plus_y, list(1:5, 5:1))
## [1] 6 6 6 6 6
# 与下相同
do.call(function(x, y) x + y, list(1:5, 5:1))
## [1] 6 6 6 6 6
小结
· 环境能存储变量, 它能够被 new.env 函数创建。
· 通常, 你可以把环境看作列表。
· 函数由形参和函数体组成。
· 你可以分配和使用函数, 像对任何其他的变量类型一样。