在array中进行隐式循环
lapply,vapply和sapply不能直接用于matrix等array中,这3个函数会将array视作vector,沿着column的方向将每个元素运算一次,因此对于array结果的数据,我们需要使用apply()函数。
apply(X, MARGIN, FUN, ...)
#MARGIN取1为row,取2为col
需要注意的是,apply函数的每一轮循环输出结果都会被as.vector()强行coerce一次,然后再根据结果长短是否一致最终输出为matrix或list。换句话说,如果隐循环每一轮本来输出的是factor,被强行coerce之后输出的就是character了,最终结果是一个character matrix。
> x=matrix(1:16,nrow = 4)
> apply(x, 1, toString) #输出的是4元素的string
[1] "1, 5, 9, 13" "2, 6, 10, 14" "3, 7, 11, 15" "4, 8, 12, 16"
在dataframe中进行隐式循环
正如前文所说,dataframe是list和array的结合体,因此sapply和apply都可以用于dataframe,但依然要时刻留意格式coerce可能造成的隐患。
多参数同时进入隐式循环
mapply()可以接受多个参数同时进入循环,但其参数传递的顺序需要注意。
#FUN是第一个传递进入的参数
mapply(FUN, ..., MoreArgs = NULL, SIMPLIFY = TRUE,
USE.NAMES = TRUE)
参数化函数
Vectorize()是一个wrapper,可以将某些不能接受vector类型参数的函数(通常为自定义)转化为能够接受vector参数的函数。
split() 和 tapply()
书中介绍了split()函数和tapply函数。但个人认为使用reshape2包中的melt()或cast()函数先把数据源处理了可能更好。。。。
split输出一个list
# split能够接受新的vector输入
split(x, f, drop = FALSE, ...)
## Default S3 method:
split(x, f, drop = FALSE, sep = ".", lex.order = FALSE, ...)
split(x, f, drop = FALSE, ...) <- value
unsplit(value, f, drop = FALSE)
而tapply是针对ragged array进行了优化的一类apply函数。
Apply a function to each cell of a ragged array, that is to each (non-empty) group of values
given by a unique combination of the levels of certain factors.
tapply(X, INDEX, FUN = NULL, ..., default = NA, simplify = TRUE)
#相当于split X by INDEX中的factor levels then apply FUN
#INDEX参数会被强行as.factor()
tapply()的两个wrapper
by()和aggregate()是tapply的两个warpper函数。by()适用于dataframe;而aggregate可用于dataframe,formula和ts三种数据类型。
by(data, INDICES, FUN, ..., simplify = TRUE)
## S3 method for class 'data.frame'
aggregate(x, by, FUN, ..., simplify = TRUE, drop = TRUE)