和Matlab一样,R语言以向量为基本运算对象。也就是说,当输入的对象为向量时,对其中的每个元素分别进行处理,然后以向量的形式输出。R语言中基本上所有的数据运算均能允许向量操作。不仅如此,R还包含了许多高效的向量运算函数,这也是它不同于其它软件的一个显著特征。向量化运算的好处在于避免使用循环,使代码更为简洁、高效和易于理解。本文来对apply族函数作一个简单的归纳,以便于大家理解其中的区别所在。
所谓apply族函数包括了apply,sapply,lappy,tapply等函数,这些函数在不同的情况下能高效的完成复杂的数据处理任务,但角色定位又有所不同。
apply()函数的处理对象是矩阵或数组,它逐行或逐列的处理数据,其输出的结果将是一个向量或是矩阵。下面的例子即对一个随机矩阵求每一行的均值。要注意的是apply与其它函数不同,它并不能明显改善计算效率,因为它本身内置为循环运算。
m.data <- matrix(rnorm(100),ncol=10)
apply(m.data,1,mean)
lappy()的处理对象是向量、列表或其它对象,它将向量中的每个元素作为参数,输入到处理函数中,最后生成结果的格式为列表。在R中数据框是一种特殊的列表,所以数据框的列也将作为函数的处理对象。下面的例子即对一个数据框按列来计算中位数与标准差。
f.data <- data.frame(x=rnorm(10),y=runif(10))
lapply(f.data,FUN=function(x) list(median=median(x),sd=sd(x)))
sapply()可能是使用最为频繁的向量化函数了,它和lappy()是非常相似的,但其输出格式则是较为友好的矩阵格式。
sapply(f.data,FUN=function(x) list(median=median(x),sd=sd(x)))
class(test)
tapply()的功能则又有不同,它是专门用来处理分组数据的,其参数要比sapply多一个。我们以iris数据集为例,可观察到Species列中存放了三种花的名称,我们的目的是要计算三种花瓣萼片宽度的均值。其输出结果是数组格式。
head(iris)
attach(iris)
tapply(Sepal.Width,INDEX=Species,FUN=mean)
与tapply功能非常相似的还有aggregate(),其输出是更为友好的数据框格式。而by()和上面两个函数是同门师兄弟。
另外还有一个非常有用的函数replicate(),它可以将某个函数重复运行N次,常常用来生成较复杂的随机数。下面的例子即先建立一个函数,模拟扔两个骰子的点数之和,然后重复运行10000次。
game <- function() {
n <- sample(1:6,2,replace=T)
return(sum(n))
}
replicate(n=10000,game())
最后一个有趣的函数Vectorize(),它能将一个不能进行向量化运算的函数进行转化,使之具备向量化运算功能。