控制流
R语言的循环和控制流包括:if、else、 next、while、for等语句。
R语句的缩进多用大括号,如for
循环后面的操作需放在大括号里面;一般来说if
条件后面的操作可以不用大括号括起来, 但是当使用if-else
结构时必须使用大括号将操作括起来。next
的作用类似于Python中的continue,表示跳过。while
表示重复操作,循环内部一般需要一个break
来跳出循环。此外,while
、for
、if
后面的条件语句都需要用小括号括起来。
R中函数直接使用<-
进行赋值给一个变量,函数使用return()
返回值,若不使用return语句,默认把最后的语句作为返回值。
func <- function(){
n<-1
while (TRUE){
if (n%%2==0){
print('even number: ',n)
}else{print('odd number: ',n)}
if(n>10)
print('too large, exit....')
break
n<-n+1
}
}
apply家族
apply
家族函数是进行向量化运算的运算方法,而且由于其基于C语言编写的,与for循环相比,能大大地提高运算速度。apply
家族函数众多,包括apply
、sapply
、lapply
、vapply
、mapply
、tapply
、rapply
、eapply
,各个函数的用途如下图所示。这里主要讲一下应用较多的apply
和sapply
函数。
1、apply
apply函数可以对矩阵、数据框、数组(二维、多维),按行或列进行循环计算,对子元素进行迭代,并把子元素以参数传递的形式给自定义的FUN函数中,并返回计算结果。使用方法如下:
apply(X, MARGIN, FUN, ...)
X 表示数组、矩阵或数据框
MARGIN 表示函数作用于行还是列,1表示行,2表示列
FUN 作用于行或列的函数
... 表示函数的参数
> options(digits=2);student <- c('andy','lucy','mike','jacky');score <- c(88,92,67,75);df<-data.frame(student,score,stringsAsFactors=FALSE);df
student score
1 andy 88
2 lucy 92
3 mike 67
4 jacky 75
> df$salary<-c(200,320,90,NA);df
student score salary
1 andy 88 200
2 lucy 92 320
3 mike 67 90
4 jacky 75 NA
> average <- apply(df[,c(2:3)],2,mean,na.rm=TRUE);df<-rbind(df,c("average",average));df
student score salary
1 andy 88 200
2 lucy 92 320
3 mike 67 90
4 jacky 75
5 average 80.5 203.333333333333
####这里需要注意的是由于行合并的时候用了c("average",average),因此average数字也被换成了字符串,为了方便后续计算,最好还是将他们转换为numeric
> df[,c(2,3)]<-apply(df[,c(2,3)], 2, as.numeric);df
student score salary
1 andy 88 200
2 lucy 92 320
3 mike 67 90
4 jacky 75 NA
5 average 80 203
再来看一个稍微复杂点的例子,这回我们使用自定义的函数,完成对矩阵的第一列加一,第二列等于行平均值:
###首先定义函数
func <- function(x, c1, c2){
c(sum(x[c1], 1), x[c2]<-mean(x[c2]))
}
###使用自定义函数
> x <- cbind(x1 = 3, x2 = c(4:1, 2:5)); x
x1 x2
[1,] 3 4
[2,] 3 3
[3,] 3 2
[4,] 3 1
[5,] 3 2
[6,] 3 3
[7,] 3 4
[8,] 3 5
> apply(x,1,func,c1='x1',c2=c('x1','x2'))
[,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8]
[1,] 4.0 4 4.0 4 4.0 4 4.0 4
[2,] 3.5 3 2.5 2 2.5 3 3.5 4
###另一种更简单的方法
> x<-data.frame(x1=x[,1]+1,x2=rowMeans(x));x
x1 x2
1 4 3.5
2 4 3.0
3 4 2.5
4 4 2.0
5 4 2.5
6 4 3.0
7 4 3.5
8 4 4.0
2、lapply
lapply函数是一个最基础循环操作函数之一,用来对list、data.frame数据集进行循环,并返回和X长度同样的list结构作为结果集。使用方法如下:
lapply(X, FUNC, ...)
X list,data.frame数据结构(使用data.frame时,作用于列)
FUN 作用函数
... 参数
> x <- list(a = 1:10, b = rnorm(6,10,5), c = c(TRUE,FALSE,FALSE,TRUE));x
$a
[1] 1 2 3 4 5 6 7 8 9 10
$b
[1] 8.2 11.0 11.0 11.9 11.4 6.0
$c
[1] TRUE FALSE FALSE TRUE
> lapply(x, fivenum)
$a
[1] 1.0 3.0 5.5 8.0 10.0
$b
[1] 6.0 8.2 11.0 11.4 11.9
$c
[1] 0.0 0.0 0.5 1.0 1.0
#######################对矩阵使用会出现错误
> x <- cbind(x1=3, x2=c(2:1,4:5));x
x1 x2
[1,] 3 2
[2,] 3 1
[3,] 3 4
[4,] 3 5
> class(x); lapply(x,sum)
[1] "matrix"
[[1]]
[1] 3
[[2]]
[1] 3
[[3]]
[1] 3
[[4]]
[1] 3
[[5]]
[1] 2
[[6]]
[1] 1
[[7]]
[1] 4
[[8]]
[1] 5
> x<-as.data.frame(x);lapply(x,sum)
$x1
[1] 12
$x2
[1] 12
3、sapply
sapply函数是一个简化版的lapply,sapply增加了2个参数simplify和USE.NAMES,主要就是让输出看起来更友好,返回值为向量,而不是list对象。
sapply(X, FUN, ..., simplify=TRUE, USE.NAMES = TRUE)
X 数组、矩阵、数据框
FUN 调用函数
... 函数参数
simplify 是否数组化,当值array时,输出结果按数组进行分组
USE.NAMES 如果X为字符串,TRUE设置字符串为数据名,FALSE不设置
> x <- cbind(x1=3, x2=c(2:1,4:5));x
x1 x2
[1,] 3 2
[2,] 3 1
[3,] 3 4
[4,] 3 5
###对矩阵进行计算结果与lapply相同,无法得到想要的结果
> sapply(x, sum);
[1] 3 3 3 3 2 1 4 5
> sapply(data.frame(x), sum);
x1 x2
12 12
###当simplify=FALSE和USE.NAMES=FALSE时候,那么sapply函数就等于lapply函数了
> sapply(data.frame(x), sum, simplify=FALSE, USE.NAMES=FALSE)
$x1
[1] 12
$x2
[1] 12
4、vapply
vapply类似于sapply,提供了FUN.VALUE参数,用来控制返回值的行名,这样可以让程序更健壮。
vapply(X, FUN, FUN.VALUE, ..., USE.NAMES = TRUE)
X 数组、矩阵、数据框
FUN 自定义的调用函数
FUN.VALUE 定义返回值的行名row.names
… 函数参数
USE.NAMES 如果X为字符串,TRUE设置字符串为数据名,FALSE不设置
#对数据框的数据进行累计求和,并对每一行设置行名row.names
> x <- data.frame(cbind(x1=3, x2=c(2:1,4:5)));x
x1 x2
1 3 2
2 3 1
3 3 4
4 3 5
> vapply(x,cumsum,FUN.VALUE=c('a'=0,'b'=0,'c'=0,'d'=0))
x1 x2
a 3 2
b 6 3
c 9 7
d 12 12
转自:
掌握R语言中的apply函数族