向量是R语言中最基本、最重要的数据结构,是构成其他数据结构的基础。R语言中的向量与数学中的向量不同,它更类似于数学中“集合”的概念,表示由一个或多个元素构成。
本节将主要介绍创建向量、向量索引、向量操作、向量运算、向量排序和向量合并的相关知识。
向量是由一系列相同数据类型的有序元素构成的数据组,如图4.1所示,相当于一维数组。向量是用来存储数值型、字符型和逻辑型数据的一维数组。
在R语言中创建向量的方法有多种,下面依次进行介绍。
图4.1 向量示意图
在R语言中,创建向量主要使用c()函数。各参数(或各元素)之间用逗号分隔,且为同一种数据类型。如果参数的数据类型不一致,则c()函数会强制将所有参数转换为同一数据类型。
使用c()函数创建数值型向量,示例代码如下:
a <- c(1,2,3,4,5) print(a)
运行程序,结果为:
1 2 3 4 5
使用c()函数创建字符型向量时,一定要为各字符加上双引号,示例代码如下:
b <- c("m","r","s","o","f","t") print(b)
运行程序,结果为:
"m" "r" "s" "o" "f" "t"
使用c()函数创建逻辑型向量,示例代码如下:
c <- c(TRUE,FALSE,TRUE,TRUE) print(c)
运行程序,结果为:
TRUE FALSE TRUE TRUE
说明
代码中的TRUE和FALSE可以简写成T和F。
在R语言中,使用冒号运算符“:”也可以创建向量。冒号运算符主要用于创建公差为1或-1的等差数列向量,其使用形式为x:y,使用规则如下:
当x<y时,将生成x, x+1, x+2, x+3,…的等差数列,公差为1,最后的元素≤y。
当x>y时,将生成x, x-1, x-2, x-3,…的等差数列,公差为-1,最后的元素≥y。
当x和y相同时,将输出只有一个元素的向量,元素为x。
下面使用冒号创建向量,示例代码如下:
1 d <- 1:20 2 print(d) 3 d <- 5.1:10.2 4 print(d) 5 d <- -2:-10 6 print(d)
运行程序,结果如图4.2所示。从运行结果可知:使用冒号运算符创建的是等差数列向量。
图4.2 冒号运算符创建向量
seq()函数也可用来创建等差数列向量,语法格式如下:
seq(from = 1, to = 1, by = ((to - from)/(length.out - 1)),length.out = NULL, along.with = NULL, ...)
参数说明如下。
from:数值型,表示等差数列开始的位置,默认值为1。
to:数值型,表示等差数列结束的位置,默认值为1。
by:数值型,表示等差数列之间的间隔。
length.out:数值型,表示等差数列的长度。
along.with:向量,表示产生的等差数列与向量具有相同的长度。
注意
by、length.out和along.with 3个参数只能输入其中一项。
示例代码如下:
1 seq(0,2,length.out=6) 2 seq(1,12,by=2) 3 seq(1,8,by=pi) 4 seq(8)
运行程序,结果如图4.3所示。
图4.3 seq()函数创建向量
rep()函数是一个重复函数,主要用于创建重复的变量或向量,语法格式如下:
rep(x, …)
参数说明如下。
x:表示向量或类向量的对象。
…:表示除x的其他参数,包括each、times和length.out。
➢ each:表示x元素重复的次数。
➢ times:表示整体重复的次数。
➢ length.out:表示向量最终输出的长度。如果过长则会被截掉,过短会根据前面的规则补上。
示例代码如下:
1 rep(1:5, 2) # 1~5重复2次 2 rep(1:5, each = 2, times = 3) # 1~5重复2次,整体重复3次 3 rep(1:5, each = 2, len = 3) # 1~5重复2次,长度为3 4 rep(1:5, each = 2, len = 12) # 1~5重复2次,长度为12
运行程序,结果如图4.4所示。
图4.4 rep()函数创建向量
在R语言中,sample()函数可以随机抽取向量,也可以从数据集中抽取指定数量的样本,返回向量或数据框。语法格式如下:
sample(x, size, replace = FALSE, prob = NULL)
参数说明如下。
x:表示被抽取的样本的来源。
size:表示抽取的样本的数量。
replace:逻辑值,表示是否重复抽样。默认值为F,表示不重复抽样,此时size参数不能大于x的长度;如果值为T,则表示重复抽样,此时size参数允许大于x的长度。
prob:表示各样本被抽取的概率。
例如,在1~20中不重复地随机创建10个元素的向量,示例代码如下:
sample(c(1:20),size=10) # 在1~20中不重复地随机创建10个元素的向量
运行程序,结果为:
[1] 15 19 7 9 13 6 5 14 12 18
例如,在1~20中重复地随机创建15个元素的向量,示例代码如下:
sample(c(1:20),size=15,replace=T) # 在1~20中重复地随机创建15个元素的向量
运行程序,结果为:
[1] 11 18 12 3 6 10 17 6 1 19 4 1 2 6 1
在R语言中,runif()函数用于生成0~1之间符合均匀分布的随机数,也可以指定最小值和最大值。
示例代码如下:
1 runif(10) # 生成10个0~1之间符合均匀分布的随机数 2 runif(10, min = 3, max = 30) # 生成10个最小值为3,最大值为30符合均匀分布的随机数
运行程序,结果如图4.5所示。
图4.5 runif()函数生成符合均匀分布的随机数
在R语言中,rnorm()函数用于生成服从正态分布的随机数。
例如,直接使用,默认生成平均数为0、标准差为1的随机数,示例代码如下:
rnorm(20)
设置平均值,生成平均数为5、标准差默认为1的随机数,示例代码如下:
rnorm(20,5)
设置平均值和标准差,生成平均数为0、标准差为9的随机数,示例代码如下:
rnorm(20, mean = 0, sd = 9)
说明
rnorm()函数生成的是随机数,因此每次运行生成的随机数都会不同。如果想要生成的随机数不发生改变,可在rnorm()函数前使用set.seed()函数。set.seed()函数的参数可以是任意数字,标记设置的是第几号种子。例如:
1 set.seed(0) 2 rnorm(20,5)
通过向量索引可访问向量中的元素。索引就是向量中元素所处位置的数值,本质上是一个编号,由系统自动生成,值为1、2…,依次类推。在方括号“[ ]”中指定元素所在位置的数值就可以访问该元素。例如,在如图4.6所示的向量a中,a[1]表示访问第1个元素,也就是3。
在R语言中,向量索引分为正(负)整数索引、逻辑索引和名称索引。
正整数索引从位置1开始,负整数索引从-1开始,如图4.7所示。正整数索引访问的是向量中该位置的元素,负整数索引访问的是向量中除了该位置的所有元素。
图4.6 访问向量a中的元素
图4.7 正(负)整数索引示意图
示例代码如下:
1 a <- c(100,90,68,77,45,88) 2 b <- c("a","b","c","d","e") 3 print(a[1]) # 访问a[1]位置的元素 4 print(b[-2]) # 访问除了b[-2]位置的所有元素
运行程序,结果如图4.8所示。
图4.8 正(负)整数索引的示例
可以使用向量访问向量中的多个元素。例如,访问向量a中1、3、5位置的元素,示例代码如下:
print(a[c(1,3,5)])
运行程序,结果为:
100 68 45
可以使用冒号连续访问向量中的元素,示例代码如下:
print(a[c(1:3)])
运行程序,结果为:
100 90 68
在R语言中,还可以使用逻辑向量作为向量索引。逻辑值为TRUE,表示输出;逻辑值为FALSE,表示不输出。默认值为TRUE,示例代码如下:
print(a[c(T,T,F,F)])
运行程序,结果为:
100 90 45 88
如果逻辑值的个数超出了向量中元素的个数,则会出现缺失值(NA),示例代码如下:
print(a[c(T,T,F,F,T,T,T,T)])
运行程序,结果为:
100 90 45 88 NA NA
说明
TRUE可以简写为T,FALSE可以简写为F。
在R语言中,还可以通过元素名称访问向量中的元素。首先需要使用names()函数为向量添加名称,然后通过名称访问向量中的元素。
示例代码如下:
1 # 为向量a添加名称 2 a <- c(100,90,68,77,45,88) 3 names(a) <- c("甲","乙","丙","丁","戊","己") 4 print(a) 5 # 通过名称索引访问向量中的元素 6 print(a["甲"]) 7 print(a[c("甲","乙","丙")])
运行程序,结果如图4.9所示。
图4.9 名称索引
向量创建完成后,需要在原始向量中添加新元素、修改元素和删除元素等,下面进行详细的介绍。
1)添加元素
在原向量中添加新元素,可以通过添加新索引并为其赋值的方法。示例代码如下:
1 a <- c(100,90,68,77,45,88) # 原始向量a 2 print(a) 3 a[c(7,8,9)] <- c(60,99,50) # 为向量a的7、8、9的索引赋值 4 print(a)
运行程序,结果为:
100 90 68 77 45 88 60 99 50
其中,“60 99 50”为新添加的元素。
2)插入元素
append()函数用于在指定位置插入元素。例如,在索引2的后面插入元素“60 99 50”,示例代码如下:
append(x = a,values = c(60,99,50),after = 2)
要想修改向量中的元素,需要先通过索引找到该元素,然后为其赋新值。例如,将索引为2的元素修改为99,示例代码如下:
1 # 原始向量a 2 a <- c(100,90,68,77,45,88) 3 a[2] <- 99 4 print(a)
运行程序,结果为:
100 99 68 77 45 88
1)删除整个向量
删除整个向量经常使用rm()函数。如删除向量a,示例代码如下:
rm(a)
2)删除向量中的某一个元素
删除向量中的某一个元素可以采用负整数索引的方式,将不需要的元素排除在外。例如,删除向量a中的前4个元素并输出剩余元素,示例代码如下:
a[-c(1:4)]
运行程序,结果为:
45 88
向量运算是指向量中元素与元素之间的加、减、乘、除、幂、求余等运算。在3.2.4节中,我们对运算符和向量运算已经有了初步了解。本节将主要介绍如何计算向量的绝对值、平方根、对数、指数、最小整数、最大整数等,如表4.1所示。
表4.1 向量运算函数
实现向量排序的主要函数有sort()、order()、rev()和rank(),下面分别进行介绍。
向量排序是对向量中的元素进行排序,主要使用sort()函数。语法格式如下:
sort(x, decreasing = FALSE, na.last = NA, ...)
参数说明如下。
x:表示要排序的对象。
decreasing:逻辑值,表示升序排序或降序排序。默认值为FALSE,表示升序排序。
na.last:缺失值NA的处理方式。取值为TRUE时,缺失值放在最后面;取值为FALSE时,缺失值放在最前面;取值为NA时(默认值),缺失值被移除,不参与排序。
【例4.1】 学生数学成绩排序 (sort()函数,实例位置:资源包\Code\04\01)
使用sort()函数对一组学生数学成绩进行排序,包括升序排序和降序排序。运行RStudio,新建一个R Script脚本文件,编写如下代码。
运行程序,结果如图4.10所示。
图4.10 学生数学成绩排序
order()函数用于返回向量排序后的位置,也就是索引,默认为升序排序。语法格式如下:
order(… = data, na.last = TRUE,decreasing = TRUE)
参数说明如下。
…:表示要排序的向量。
na.last:逻辑值,表示排序时是否将NA值放在最后,默认NA值放在最后。
decreasing:逻辑值,表示升序排序还是降序排序,默认为升序排序。
【例4.2】 学生数学成绩排序 (order()函数,实例位置:资源包\Code\04\02)
使用order()函数将学生数学成绩排序,对比sort()函数,分析结果有什么不同。运行RStudio,编写如下代码。
1 a <- c(89,90,120,110,78,99,130,56,88,130,145,120,NA) # 创建向量数据 2 print(a) 3 result <- order(a) # 升序排序 4 print(result)
运行程序,结果为:
8 5 9 1 2 6 4 3 12 7 10 11 13
这个排序结果是向量索引,是学生成绩数据对应的索引,如图4.11所示。
图4.11为排序前的向量索引,使用order()函数排序后,向量索引变为8 5 9 1 2 6 4 3 12 7 10 11 13。其中,13为NA值,被放在了最后。
rev()函数用于反向(逆序)排列向量,示例代码如下:
1 rev(1:10) 2 rev(c('a','b','c','d','e'))
运行程序,结果如图4.12所示。
图4.11 向量索引示意图
图4.12 反向排列向量
rank()函数用于排名,返回向量中各元素的排名,默认为升序。语法格式如下:
rank(x, na.last = TRUE,ties.method = c("average", "first", "random", "max", "min"))
参数说明如下。
x:表示要排名的向量。
na.last:逻辑值,表示排名时是否将NA值放在最后,默认NA值放在最后。
ties.method:表示排名方式,包括5个值。
➢ first:最基本的排名方式,从小到大排序。相同的元素先者在前,后者在后。
➢ max:相同元素取该组中最好的水平,即并列排名。
➢ min:相同元素取该组中最差的水平,以增大序列的等级差异。
➢ average:相同元素取该组中的平均水平,该水平可能是个小数。
➢ random:相同元素随机编排名次,避免“先到先得”,“权重”优于“先后顺序”的机制增大了随机程度。
【例4.3】 学生数学成绩排名 (rank()函数,实例位置:资源包\Code\04\03)
使用rank()函数对学生成绩排序,获取各学生的名次。运行RStudio,新建一个R Script脚本文件,编写如下代码。
1 a <- c(89,90,120,110,78,99,130,56,88,130,145,120,NA) # 创建向量数据 2 print(a) 3 result <- rank(a) # 升序排名 4 print(result)
运行程序,结果为:
4.0 5.0 8.5 7.0 2.0 6.0 10.5 1.0 3.0 10.5 12.0 8.5 13.0
这些数字代表着每个成绩的名次,13为NA值,被放在了最后。
在数据处理中,向量合并是一种常见操作,它可以将不同的向量按照一定的规则合并为一个更大的向量。在R语言中,合并向量主要使用c()函数、rbind()函数和cbind()函数,下面分别进行介绍。
使用c()函数可以将两个或多个向量按顺序合并为一个向量,示例代码如下:
1 a <- c(1,2,3,4) 2 b <- c(5,6,7,8) 3 c(a,b)
运行程序,向量a和向量b合并后,结果如下:
[1] 1 2 3 4 5 6 7 8
rbind()函数和cbind()函数用于将两个或多个向量按照行或列将向量或矩阵合并为一个矩阵,示例代码如下:
1 rbind(a,b) # 按行合并 2 cbind(a,b) # 按列合并
运行程序,结果如图4.13所示。
图4.13 将向量合并为矩阵