(四)控制流、函数与apply家族

控制流

R语言的循环和控制流包括:if、else、 next、while、for等语句。
R语句的缩进多用大括号,如for循环后面的操作需放在大括号里面;一般来说if条件后面的操作可以不用大括号括起来, 但是当使用if-else结构时必须使用大括号将操作括起来。next的作用类似于Python中的continue,表示跳过。while表示重复操作,循环内部一般需要一个break来跳出循环。此外,whileforif后面的条件语句都需要用小括号括起来。
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家族函数众多,包括applysapplylapplyvapplymapplytapplyrapplyeapply,各个函数的用途如下图所示。这里主要讲一下应用较多的applysapply函数。

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函数族

你可能感兴趣的:((四)控制流、函数与apply家族)