三、数组 Array
先前的向量Vector和矩阵Martrix只支持一维和二维的运算,为支持更高更灵活维度的运算,R语言引入了和其他语言类似的数组(Array)类型
1. 创建
- 创建数组-
array(向量)
| 参数 | dim = lengh(向量) | dimnames = NULL |
|---|---|---|
| 类型 | vector | list |
| 含义 | 各维度长度 | 各维度命名 |
需要满足length(向量) == prod(dim),而后按照维度从前到后填充(行 → 列 → 第三维 → …)
其他与矩阵Matrix类似,不多赘述,看示例:
array(c("w","i","n","d",2,0,6,7),dim=c(2,2,2))#, , 1## [,1] [,2]#[1,] "w" "n"#[2,] "i" "d"##, , 2## [,1] [,2]#[1,] "2" "6"#[2,] "0" "7"为节约篇幅并排除水文的嫌疑,此后数组Array的输出会稍作调整
- 维度命名-创建时
向dimnames传入一个包含各维度命名向量的列表list
array(c("w","i","n","d",2,0,6,7),dim=c(2,2,2))#, , 1 , , 2# [,1] [,2] [,1] [,2]#[1,] "w" "n" [1,] "2" "6"#[2,] "i" "d" [2,] "0" "7"array(c("w","i","n","d",2,0,6,7),dim=c(2,2,2),dimnames=list(c(1,2),c(1,2),c("name","code")))#, , name , , code# 1 2 1 2#1 "w" "n" 1 "2" "6"#2 "i" "d" 2 "0" "7"更高维度的默认命名为, , 3维取值, 4维取值, ..., n维取值
前两个,取值的缺省表示打印了当前缺省组合所有内容,如, ,表示打印了前两维度所有内容
同理,[,i]表示当前列打印了该列所有内容
2. 访问
同样地,数组Array支持用[1维取值, 2维取值, ..., n维取值]来访问元素、低阶分块、同阶分块
a) 用索引访问
creator<-array(c("w","i","n","d",2,0,6,7),dim=c(2,2,2))creator[1,2,2]#[1] "6"creator[-1,2,2]#[1] "7"creator[,,2]# [,1] [,2]#[1,] "2" "6"#[2,] "0" "7"creator[1:1,1:2,1:2]# [,1] [,2]#[1,] "w" "2"#[2,] "n" "6"creator[1:1,1:2,c(1,1)]# [,1] [,2]#[1,] "w" "w"#[2,] "n" "n"在访问低阶分块时,数据依旧保持原先的维度顺序,如例中2、3维的数据各对应结果中1、2维
b) 用命名访问
creator<-array(c("w","i","n","d",2,0,6,7),dim=c(2,2,2),dimnames=list(c(1,2),c(1,2),c("name","code")))creator[1,2,"code"]#[1] "6"creator[,,"code"]# 1 2#1 "2" "6"#2 "0" "7"creator[1:1,1:2,c("name","code")]# name code#1 "w" "2"#2 "n" "6"3. 运算
- 遍历操作-
apply(数组[矩阵也可], ...[附加参数])
| 参数 | MARGIN | FUN | … |
|---|---|---|---|
| 类型 | integer | function | undefined |
| 含义 | 应用操作的维度 | 实施操作的函数 | 若函数有多个参数,在此处补充 |
遍历某个维度的所有向量,对每个向量进行操作 ,结果按该维度的序号顺序拼成矩阵
若MARGIN长度大于1,则遍历对象为MARGIN提供维度数组,结果的顺序为第一维度
code<-array(c(2,0,6,7),dim=c(1,2,2))>code,,1,,2[,1][,2][,1][,2][1,]20[1,]67# 计算每列的和apply(code,MARGIN=2,FUN=sum)#[1] 8 7# 每项加1increase<-function(vec){res<-vector()for(eleinvec)res<-c(res,ele+1)return(res)}# 按第一维度向量、二、三维度矩阵、所有维度三维数列操作apply(code,MARGIN=1,FUN=increase)# [,1]#[1,] 3#[2,] 1#[3,] 7#[4,] 8apply(code,MARGIN=c(1,2),FUN=increase)#, , 1 , , 2# [,1] [,1]#[1,] 3 [1,] 1#[2,] 7 [2,] 8apply(code,MARGIN=c(1,2,3),FUN=increase)#, , 1 , , 2# [,1] [,2] [,1] [,2]#[1,] 3 1 [1,] 7 8后面两个读起来确实比较费力,读者可以联系前面的表述理解输出格式
4. 模拟
可以用列表的嵌套模拟数组,如此数组的元素可以是更多的数据类型,此处暂略
四、因子 Factor
R语言的因子用于存储离散的、取值有限的数据,如一群人的性别可以用因子存储
因子中数据的取值称为水平level,如上例中因子的水平为
"男"、"女"
1. 创建
- 根据数据创建因子-
factor(向量)
| 参数 | levels | labels = levels | ordered = F | exclude = NA | nmax = NA |
|---|---|---|---|---|---|
| 类型 | undefined | vector | logical | undefined | integer |
| 含义 | 水平 | 水平命名[标签] | 水平是否有序 | 排除无效字符 | 水平数上限 |
不填写levels时,其默认为传入向量的所有不重复元素
若填写,将选择性接收传入值,levels不含有的为NA
factor(c('female','male','female','female','male'))#[1] female male female female male#Levels: male femalefactor(c('female','male','female','female','male'),ordered=T)#[1] female male female female male#Levels: male **<** femalefactor(c('female','male','female','walmatBag','female','male'),exclude="walmatBag")#[1] female male female <NA> female male#Levels: female malefactor(c('female','male','female','walmatBag','female','male'),levels=c("male","female"))#[1] female male female <NA> female male#Levels: male female- 水平命名-创建时
使用labels参数命名,顺序与levels一致
注意,此时因子的数据和水平将全部以labels的形式存储
factor(c(0,1,0,0,1),levels=c(1,0),labels=c("male","female"))#[1] female male female female male#Levels: male female若未显式指定levels参数,其默认顺序为数字、字母从小到大
factor(c(6,7),labels=c("fir","sec"))#[1] fir secfactor(c(2,0),labels=c("fir","sec"))#[1] sec firfactor(c('w','i'),labels=c("fir","sec"))#[1] sec firfactor(c("wi","nd"),labels=c("fir","sec"))#[1] sec firfactor(c("wi","wn"),labels=c("fir","sec"))#[1] fir sec- 根据水平重复创建因子-
gl(水平数, 重复数),generate factorlevels
| 参数 | length = n * k | labels = levels | ordered = F |
|---|---|---|---|
| 类型 | integer | vector | logical |
| 含义 | 因子长度 | 水平命名[标签] | 水平是否有序 |
length参数的优先级高于重复数
gl(2,3)#[1] 1 1 1 2 2 2#Levels: 1 2gl(2,3,length=4)#[1] 1 1 1 2#Levels: 1 2gl(2,3,length=8)#[1] 1 1 1 2 2 2 1 1#Levels: 1 2gl(2,3,labels=c("wind","2067"))#[1] wind wind wind 2067 2067 2067#Levels: wind 20672. 访问
因子存储的内容与向量无异,向量的访问方式也适用于因子,结果均为因子
code<-c(2,0,6,7)creator<-factor(code)# numericcreator[1]#[1] 2#Levels: 0 2 6 7# logicalcreator[c(T,F,T,F)]#[1] 2 6#Levels: 0 2 6 73. 操作
a) 信息获取
- 获取水平数-
nlevels(因子)
code<-c(2,0,6,7)creator<-factor(code,levels=code,labels=c('w','i','n','d'))nlevels(creator)#[1] 4- 获取水平向量-
levels(因子)
code<-c(2,0,6,7)creator<-factor(code,levels=code,labels=c('w','i','n','d'))levels(creator)#[1] "w" "i" "n" "d"若修改该向量,对应因子的水平向量也会改变
creator<-factor(code,levels=code,labels=c('w','u','n','d'))creator#[1] w u n d#Levels: w u n dlevels(creator)<-c(c('w','i','n','d'))creator#[1] w i n d#Levels: w i n d- 判断因子是否有序-
is.ordered(因子)
is.ordered(factor(c(),ordered=T))#[1] TRUE- 逻辑判断,如是否处于某水平
code<-c(2,0,6,7)creator<-factor(code,levels=code,labels=c('w','i','n','d'))which(creator=="i")#[1] 2注意,在命名之后水平向量及数据都以labels的形式存储
which(creator==0)#integer(0) 表示未找到b) 修改数据
- 置顶某水平-
relevel(因子)
| 参数 | ref |
|---|---|
| 类型 | character |
| 含义 | 置顶水平 |
code<-factor(c(2,0,6,7))#[1] 2 0 6 7#Levels: 0 2 6 7relevel(code,ref=2)#[1] 2 0 6 7#Levels: 2 0 6 7- 重新排序水平-
reorder(因子x, 排序向量X)
| 参数 | FUN = mean | order = is.ordered(x) |
|---|---|---|
| 类型 | function | logical |
| 含义 | 操作函数 | 结果因子是否有序 |
要求排序向量长度与因子数据长度一致,排序向量每个元素对应一个水平
于是此时每个水平将获得这些元素组成的向量,水平根据向量经操作函数处理的结果升序排序
# 实际问题1: 根据平均身高排序地区region<-c('A','A','B','C','B')height<-c(1.6,1.7,1.8,1.7,1.9)fRegion<-factor(region)reorder(fRegion,height,FUN=mean)#[1] A A B C B#attr(,"scores")# A B C#1.65 1.85 1.70#Levels: A C B# 实际问题2: 根据数据量排序水平fData<-factor(c(2,0,6,0,6,7,2,6,7))reorder(fData,rep(1,length=length(fData)),FUN=sum)#[1] 2 0 6 0 6 7 2 6 7#attr(,"scores")#0 2 6 7#2 2 3 2#Levels: 0 2 7 6- 删除未使用的水平-
droplevels(因子)
empty<-factor(c(),levels=c(2,0,6,7))empty#factor()#Levels: 2 0 6 7droplevels(empty)#factor()#Levels:- 有序转化-
as.order(因子)
code<-factor(c(2,0,6,7))#[1] 2 0 6 7#Levels: 0 2 6 7as.ordered(code)#[1] 2 0 6 7#Levels: 0 < 2 < 6 < 74. 应用
向等长数据载体应用因子,相当于为数据打上了标签,如此就能分组处理数据
支持使用list()组合多个因子,此时只有这些因子都对应相同的数据才能分为一组
- 按因子拆分数据-
split(数据载体, 因子)
fTag<-factor(c(1,2,1,3,1))data<-c(2,0,6,7,6)split(data,fTag)#$`1`#[1] 2 6 6##$`2`#[1] 0##$`3`#[1] 7- 按因子应用函数[向量]-
tapply(向量, 因子, 函数)
相当于在分组的基础上,对组向量施加操作函数,结果为表格
# 使用上例的数据,计算组均值tapply(data,fTag,mean)# 1 2 3#4.666667 0.000000 7.000000- 按因子应用函数[矩阵]-
by(矩阵, 因子, 函数),因子将作用于行
# 分组后计算组内列均值mat<-matrix(c(2,0,6,7,6,7,2,0),ncol=2)mat# [,1] [,2]#[1,] 2 6#[2,] 0 7#[3,] 6 2#[4,] 7 0fTag<-factor(c(1,0,1,1))by(mat,fTag,colMeans)#INDICES: 0#V1 V2# 0 7#---------------------------------------#INDICES: 1# V1 V2#5.000000 2.666667