R是一门著名的可用于数据和统计分析的程序语言,本文翻译自R软件官方文档教程《An Introduction to R》,仅供学习和参考。
2 数字和向量的简单操作
2.1 向量和赋值
R中的数据结构都是以名称为标识来进行操作的。
最简单的数据结构当然是数值向量(vector
),它由一组有前后顺序的数字组成。为了建立一个名为"x"的向量,比如一个包含5个数字10.4、 5.6、 3.1、 6.42、1.7的向量,你可以输入以下命令:
x <- c(10.4, 5.6, 3.1, 6.42, 1.7)
这是一条赋值语句。它使用到了c()
函数。在上面的情形中,c()
接受任意个向量,并把这些向量的元素以从头到尾的顺序结合(combine
)成一个新的向量。
在上面的语句中,一个数字可以看成是一个长度(length
)为1的向量。
注意到,赋值符号是<-
,由紧紧相邻的<
和-
组成。箭头<
所指的方向,就是接受赋值的对象。大多数情形下,可以用=
进行平替(不是很建议)。
赋值的操作,也可以用assign()
函数实现:
assign("x",c(10.4, 5.6, 3.1, 6.42, 1.7)
实际上,<-
符号只是assign
函数的一种快捷方式。
赋值符号也可以换个方向,即:
c(10.4, 5.6, 3.1, 6.42, 1.7) -> x
赋值式一般不会打印出结果。如果仅有赋值语句右边的表达式,表达式的结果将被打印,并且销毁。例如:
> 1/x
[1] 0.09615385 0.17857143 0.32258065 0.15576324 0.58823529
对x
赋值后,我们也可以用x
进行进一步的赋值,如:
> y <- c(x,0,x)
> y
[1] 10.40 5.60 3.10 6.42 1.70 0.00 10.40 5.60 3.10 6.42 1.70
2.2 向量运算
向量可以用于算术表达式。在算术表达式中,会将向量的各个分量进行对应的运算。
进行运算的向量未必要长度相同。如果长度不相同,最后的计算结果的长度会等于表达式中最长向量的长度。那些比较短的向量会自动循环补齐,直至长度与最长向量相同。作为特例,一个数字,将会被拓展为与最长向量等长的常数向量。
> v <- 2*x + y + 1
Warning message:
In 2 * x + y : 长的对象长度不是短的对象长度的整倍数
> v
[1] 32.20 17.80 10.30 20.26 6.10 21.80 22.60 12.80 16.94 10.82 23.50
上面的代码中,x
长为5,y
长为11,1
长为1。最终结果v
的长度应为11。x
被拓展为c(10.4, 5.6, 3.1, 6.42, 1.7,10.4, 5.6, 3.1, 6.42, 1.7,10.4)
。1被拓展为c(1,1,1,1,1,1,1,1,1,1,1)
。最后的结果由相应位置的分量运算而得。
最基本的算术运算符和数学中一样,有+
、-
、*
、/
,而^
代表次方运算。
除此之外,R还提供了一系列常见的数学函数,如log()
、exp()
、sin()
、cos()
、tan()
、sqrt()
等。
min(x)
和max(x)
可以分别选出向量x
中的最小值和最大值。其实,你还可以向它们传入多个向量,最终的结果理所当然是所有的向量元素中的最小值和最大值。
pmin()
和pmax()
可以接受多个向量作为参数。先通过循环拓展机制将它们补至最长,再比较每一个下标,多个向量比较之后产生的最小值或最大值。也就是,返回值为长度与最长参数向量相同的一个最值向量。这称为并行最小值/最大值。
range(x)
可以同时给出向量x
中的最小值和最大值,相当于c(min(x),max(x))
。
length(x)
返回向量x
的长度。
sum(x)
求向量x
的元素之和。prod(x)
求向量x
的元素之积。
mean(x)
和var(x)
是两个和统计有关的函数,它们分别计算样本向量x
的平均值和方差。如果向var()
传入一个p
×
\times
×n的矩阵,它将会把每列当成一个属性向量,最终返回的结果将是n
×
\times
×n的协方差矩阵。
sort(x)
返回升序排序后的x
向量。当然,还有很多其他更灵活的排序方式(详见order()
或sort.list()
)
大多数情形下,你无需在乎数值型向量中的值是整数、实数还是复数。实际上,所有的计算操作都是将数字作为double
类型浮点数或double
类型复数浮点数来进行计算的。
如果你想使用复数,请明确表达出来,否则会默认当做实数浮点数来进行处理。
> sqrt(-17) # 未指明是复数,结果将为NaN
[1] NaN
Warning message:
In sqrt(-17) : 产生了NaNs
> sqrt(-17+0i) # 指明是复数
[1] 0+4.123106i
2.3 生成常见的序列
R有很多可以生成常见数列的方法。
比如,1:30
生成c(1,2,···,29,30)
。冒号:
在语句中具有很高的优先级,也就是说,2*1:15
将会生成c(2,4,···,,28,30)
,而1:n-1
和1:(n-1)
的结果也会不同。
可以预想到的是,30:1
将会生成倒过来的数组,即c(30,29,···,2,1)
。
:
的完全体是seq()
函数,它能用来生成更多的等差数列。seq()
函数总共有5个参数,这些参数可以搭配起来使用。
seq(a,b)
和a:b
的结果一致。
R的函数,例如seq()
,可以通过参数名来指定参数,如果使用这样的指定方式,那么参数的顺序就不怎么重要了。seq()
的前两个参数名为from
和to
,分别指定序列的开端与结束。seq(from=1,to=30)
,seq(to=30,from=1)
以及1:30
的结果都是一样的。
seq()
的另外两个参数是by
和length
,可以分别以步长或总长度的方式生成序列。如果二者都没有指定,默认by=1
。
> seq(1,50,by=5)
[1] 1 6 11 16 21 26 31 36 41 46
> seq(1,50,length=6)
[1] 1.0 10.8 20.6 30.4 40.2 50.0
seq()
的第五个参数为along
,应该给它传一个向量x
,这样它就会生成长度为length(x)
的一个序列。如果不指定其他参数,将生成c(1, 2, …, length(x))
另一个使用频率很高的函数为rep()
。它的常见用法为:
> rep(x,times=5) # 整个向量重复5遍
[1] 1 2 3 1 2 3 1 2 3 1 2 3 1 2 3
> rep(x,each=5) # 每个元素重复5遍
[1] 1 1 1 1 1 2 2 2 2 2 3 3 3 3 3
2.4 逻辑向量
就像数值向量一样,R也支持逻辑向量。逻辑向量的元素为TRUE
或T
(真)、FALSE
或F
(假)、NA
(Not Available)。
逻辑向量一般由逻辑运算产生。结果逻辑向量对应位置的逻辑值代表对应位置元素关系的判断结果。如
> x<-c(2,3,4,5,6)
> result = x>4
> result
[1] FALSE FALSE FALSE TRUE TRUE
常见的逻辑运算符有>
、>=
、<
、<=
、==
(相等)、!=
(不相等)。
常见的逻辑复合词有&
(交集,且)、|
(并集,或)、!
(非)。
逻辑向量的值在参与数值运算的过程中,会被强制转换为数值向量,TRUE
转化为1
,FALSE
转化为0
2.5 缺失值
在一些情况下,一个向量的某些元素可能是未知的。在统计学意义上,未知元素或者说未知值将被当做缺失值,并用特殊值NA
(Not Available)进行标识。
is.na(x)
能返回一个和x
等长的逻辑向量,如果对应位置元素为NA
,那么逻辑向量中同位置的值将为TRUE
。如:
> x<-c(1,3,NA,5,NA)
> is.na(x)
[1] FALSE FALSE TRUE FALSE TRUE
对NA
进行运算将产生NA
。因此,两个NA
并不相等,它们仅仅只是缺失值的一种标识。NA==NA
、1==NA
的结果,都是NA
还有一种“缺失值”,它们在不可求结果的数值运算过程中产生,标记为NaN
(Not a Number),如
> 0/0
[1] NaN
> Inf-Inf
[1] NaN
is.na(x)
对NA
和NaN
一视同仁。为了区别出NaN
,你可以使用is.nan(x)
字符向量里的NA
有时被打印成<NA>
2.6 字符串向量
字符串和字符串向量在R中经常使用,比如绘图时作为标签。R中的字符串需要用""
括起来,如"x labels"
,Hello World
。
R语言支持使用""
或''
来标识字符串边界,但打印的时候一般都打印""
,少数时候不带边界引号。
R语言支持C语言风格的转义字符。比如,\\
代表\
,\"
代表"
。其他常见的转义字符有:
\n | \t | \b |
---|---|---|
换行 | tab制表符 | 后退键 |
?Quotes
可以查看完整的的转义字符表。
字符串可以作为字符向量的组成部分。字符向量可以通过c()
函数来合成一个更长的字符向量。
patse()
函数可以接受任意多个字符向量,并把这些字符向量的元素按照一一对应的关系拼接成新的字符串,然后返回由这些字符串组成的字符向量。默认会在拼接的时候加上空格,但可以通过seq=<string>
参数修改这个默认值。
> x <- c("A","B","C")
> y <- c(1,2,3)
> paste(x,y)
[1] "A 1" "B 2" "C 3"
> paste(x,y,sep="_")
[1] "A_1" "B_2" "C_3"
2.7 通过索引向量访问或修改数据子集
可以通过向量名[索引向量]
的方式来访问数据子集。
常见的索引向量有四种类型。
- 逻辑向量。这种情况下,逻辑索引向量应该和原向量等长。对应位置为
TRUE
的元素将保留下来。如:
> x<-c(-2,-1,NA,0,1,2,NA)
> y1 <-x[!is.na(x)] # 选中非缺失值
> y1
[1] -2 -1 0 1 2
> y2 <- x[(!is.na(x)) & (x>0)] # 选中非缺失的正值
> y2
[1] 1 2
- 正整数向量。这种情况下,正整数索引向量的元素应该在
c(1,2,3,···,length(x))
中取,代表原向量的位置下标。正整数索引向量的可以任意长,最终的结果向量会和索引向量等长,对应位置的值正是对应下标的值。
> x<-c(-2,-1,NA,0,1,2,NA)
> x[5] # 单个值
[1] 1
> x[c(1,3,5)] # 对应下标的值
[1] -2 NA 1
> x[1:5] # 冒号产生的序列
[1] -2 -1 NA 0 1
> x[rep(c(2,3,4),times=3)] # 其他产生序列的函数
[1] -1 NA 0 -1 NA 0 -1 NA 0
- 负整数向量。和正整数索引向量的作用相反,把对应下标的值从原向量中删去。
> x<-c(-2,-1,NA,0,1,2,NA)
> x[-5]
[1] -2 -1 NA 0 2 NA
> x[-c(1,3,5)]
[1] -1 0 2 NA
> x[-(1:5)]
[1] 2 NA
- 字符串向量。这种情况下,原向量必须要有一个
names
属性。这个names
属性给向量的每个元素起一个名字。接下来的操作,就和正整数索引向量差不多了。字符串索引向量比整数索引向量更加易于理解和操作。
> fruit <- c(5, 10, 1, 20)
> names(fruit) <- c("orange", "banana", "apple", "peach")
> lunch <- fruit[c("apple","orange")]
> lunch
apple orange
1 5
也可以通过向量名[索引向量]<-值
的方式来修改数据子集。
> x<-c(-2,-1,NA,0,1,2,NA)
> x[is.na(x)] <- 0 # 缺失值填充
> x
[1] -2 -1 0 0 1 2 0
> x[x<0] <- -x[x<0] # 取绝对值
> x
[1] 2 1 0 0 1 2 0
> x[2] <- -2 # 修改某一个数
> x
[1] 2 -2 0 0 1 2 0
> x[x<0] <- abs(x[x<0]) # # 取绝对值
> x
[1] 2 2 0 0 1 2 0
2.8 其它对象类型
向量是R中最重要的数据对象。但以下的对象类型也很常见,你将会在之后碰见他们。
matrix
(矩阵)/array
(数组)。可以看成多维的向量。factor
(因子)。用于处理分类变量。list
(列表)。元素类型不一定相同的向量。data frame
(数据框)。表格型数据。function
(函数)