ifelse()函数根据给定test值的真假,返回yes或no值。
ifelse(
test, #保存真假值的对象
yes, #test为真时,选择该值
no #test为假时,选择该值
)
# 例如
x <- c(1,2,3,4,5)
ifelse(x %% 2 == 0,"even","odd")
[1] “odd” “even” “odd” “even” “odd”
R中的循环语句分为for、while和respeat。
语法 | 含义 |
---|---|
for ( i in data) { 使用i的语句 } | 将data中的各值分别赋予变量i,同时针对每个i执行语句块中的语句 |
while (ond) { cond为真时要执行的语句} | 不断判断条件的cond的真假,条件cond为真时,执行{}中的语句,直到cond为假,退出循环 |
repeat { 要循环执行的语句 } | 反复执行{}中的语句,直至遇到退出条件。类似于其他语言中的do-while |
循环语句中,使用break与next语句可以调整循环语句的执行流程。
运算符与函数 | 含义 |
---|---|
+,-,*,/ | 四则运算 |
n %% m | 求n/m的余数 |
n %/% m | 求n/m的商 |
n^m | 求n的m次方 |
exp(n) | 求e的n次方 |
log(x,base=exp(1)) | 求logbase(x)。若不指定base,则计算loge(x) |
log2(x),log10(x) | 分别计算log2(x)和log10(x) |
sin(x),cos(x),tan(x) | 三角函数 |
借助向量运算可以很容易地从数据框中保存的数据获取所需信息,其基本原理是通过向量数据框指定逻辑值以获取特定行。例如,
d <- data.frame(x=c(1,2,3,4,5),y=c("a","b","c","d","e"))
d[c(TRUE,FALSE,TRUE,FALSE,TRUE),]
x y
1 1 a
3 3 c
5 5 e
因此,只要通过向量运算构建行选择标准TRUE和FALSE,即可选定特定行。例如,下列示例选择x为偶数的行:
d[d$x %% 2 == 0,]
x y
2 2 b
4 4 d
数据包含NA时,运算结果都会变为NA。为了解决这一问题,R中许多函数都接受na.rm作为参数。数据包含NA时,使用na.rm指定是否要将NA值从运算中排除。
sum(c(1,2,3,NA))
[1] NA
sum(c(1,2,3,NA),na.rm=TRUE)
[1] 6
常见的NA处理函数:
函数 | 含义 |
---|---|
na.fail(object,…) | 若object中包含NA,则失败 |
na.omit(object,…) | 若object中包含NA,则排除含有NA的行 |
na.exclude(object,…) | 若object中包含NA,则排除,这与na.omit相同。但使用naresid、napredict的函数中,通过NA排除的行会再次添加到结果 |
na.pass(object,…) | 即使object中包含NA,也使之通过 |
df <- data.frame(x=1:5, y=seq(2,10,2))
df [3, 2]=NA
df
X Y
1 1 2
2 2 4
3 3 NA
4 4 8
5 5 10
假设这些数据遵循y=ax+b的线性模型,该模型可以使用线性回归函数lm()创建。若向创建的模型应用resid()函数,则可以求取线性模型的预测值与实际y值之间的残差(residual)。(有关线性回归、lm、resid函数的内容将在第8章讲解。)
lm()函数带有na.action参数,该参数值不同,处理含有NA值的行的方法也不同。比如,若设置na.action=na.omit,则建模时含有NA值的第3行就被排除。因此,虽然df共有5行数据,但resid()的结果共有4个值,如下所示。
resid(lm(y ~ x, data=df, na.action=na.omit))
1 2 4 5
-2.982647e-16 3.439354e-16 1.612526e-16 -2.069233e-16
若设置na.action =na.exclude,建模时含有NA的行仍然会被排除。但求残差时,含有NA的行的残差会在结果中显示,并记作NA。因此,resid()的结果长度与原数据长度是一致的。
resid(1m(y -x, data=df, na.action=na.exclude))
1 2 3 4 5
-2.982647e-16 3.439354e-16 NA 1.612526e-16 -2.069233e-16
R中定义函数的方法与其他编程语言中的类似,但也有如下几点不同。首先,返回值时要使用类似函数调用的形式“return(返回值)”,而非“return返回值”。其次,若省略return(),则函数最后一条语句的返回值即为整个函数的返回值。利用这一特征可以重写上述fibo()函数,如下所示。
fibo <- function(n) {
if (n == 1 || n == 2) {
1
} else {
fibo(n-1) + fibo(n-2)
}
}
在R函数的帮助中,常常会看到参数列表中含有…。一方面,…表示函数的参数个数未知;另一方面,它也表示要传递给(在函数内部调用的)其他函数的参数。下列是可变长参数…的使用示例。函数f的定义中,使用…作为参数,将其逐个输出到屏幕。
f <- function(...){
args <- list(...)
for (a in args){
print(a)
}
}
f('3','4')
[1] “3”
[1] “4”
借助嵌套函数可以提取某个函数内部要反复执行的一些操作,以形成一个函数。需要执行这些操作时,只需调用构建好的嵌套函数。这不仅能使代码变得简洁,也会让使用变得更简单。此外,由于内部函数也可以访问外部函数定义的变量,所以常用作闭包(closure)。
fc- function(x1){
return(function(x2) {
return(x1 +x2)
})
}
g<-f(1)
g(2) #x1 = 1,x2= 2
[1] 3
g2 <- f(2)
g2(2) #x1= 2,x2 = 2
[1] 4
如上代码所示,函数g()中,x1=1;函数g20中,x1=2,所以g(x2)计算的是1+x2,而g2(x2)计算的是2+x2。
rm()删除指定环境中的对象;ls()返回对象名称。
rm(
…, #待删除的对象列表
list=character(), #含有待删除对象的向量
envir=as.environment(pos) #待删除对象的环境
)
ls(
name, #对象所在环境的名称
envir #代替name直接设置环境
) #返回值是包含对象名称的字符串向量。
使用rm(list=ls())命令可以删除内存中的所有对象。
若想在函数中为变量或全局变量赋值,则应使用<<-运算符。
b <- 0
f <- function(){
a <- 1
g <- function(){
a <<- 2
b <<- 2
print(a)
print(b)
}
g()
print(a)
print(b)
}
f()
[1] 2
[1] 2
[1] 2
[1] 2
对象复制追踪函数
函数 | 含义 |
---|---|
tracemen(x) | 对对象复制进行追踪 |
untracemen(x) | 取消对象复制追踪 |
队列是一种“先进先出”(First In First Out, FIFO)的数据结构。可以将队列视为一个个人依次排成的一个队伍,处理事情时总先从站在队首的人开始,新来的人要排在队尾等待。队列由以下3个函数实现:
编写支持这3种函数的队列,如下所示:
q <-c()
q size <- 0
enqueue <- function(data){
q <<- c(q, data)
q size <<- q_size + 1
} #入队
dequeue <- function(){
first <- q[1]
q <<- q[-1]
q_size <<- q_size - 1
return(first)
} #出队
size <- function(){
return(q_size)
}
上述代码中,队列使用向量q保存其数据,q_size记录队列中保存的数据个数。
函数cnqueue()中,将从参数接收到的数据与q中的原有数据拼接为新向量,然后赋给变量此时,要使用<-赋值运算符为全局变量q赋值,最后将q_size的值增加1。
函数dequeue()中,首先将q中保存的第一个元素赋给first,然后将除第一个数据外的所有数据保存到q,最后返回first,并且要将q_size减1。
函数size()返回q的长度,即q_size。
但是上述函数,在其他地方直接操作对q进行赋值,而不通过相关函数,在调用size函数时,队列长度不会发生变化。因此,需要将队列全部代码与相关变量隐藏到1个函数。
queue <-function(){
q<-c()
q_size<- 0
enqueue <- function(data){
q <<- c(q, data)
q_size <<- q_size + 1
}
dequeue <- function(){
first <- q[1]
q <<- q[-1]
q_size <<- q_size -1
return(first)
}
size <- function(){
return(q_size)
return(list(enqueue=enqueue, dequeue=dequeue, size=size))
}
}
[参考书目] 徐珉久,R语言与数据分析实战,2017