R语言最基本的数据类型是向量(vector)
一些重要的概念
循环补齐:在一定情况下自动延长向量。
筛选:提取向量子集。
向量化:对向量的每一个元素应用函数。
这些运算是R编程的核心
- 标量、向量、数组与矩阵
R语言中变量类型称为模式(mode)。回顾前面的学习。同一向量中的所有元素必须是相同的模式,可以是整型、数值型(浮点数)、字符型(字符串)、逻辑型(布尔逻辑)、复数型等等。如果在程序中查看变量x的类型,可以调用函数typeof(x)进行查询。
不同于ALGOL家族的编程语言(比如C和Python)中的向量索引,R中向量索引从1开始。
- 添加或删除向量元素
R中向量是连续存储的,因此不能插入或删除元素,而这跟Python语言中的数组不同。在R中,向量的大小在创建时已经确定,因此如果想要添加或删除元素,需要重新给向量赋值。例如,把一个元素添加到一个四元向量的中间,如下代码所示:
> x<-c(88,5,12,13)
> x<-c(x[1:3],168,x[4]) #insert 168 before 13
> x
[1] 88 5 12 168 13
在这里,我们创建了一个四元向量,赋值给x。为了在其第三和第四元素之间插入一个新的元素168,我们把x的前三个元素、168和x的第四个元素按顺序连起来,这样就创建出新的五元向量,而此时x并没发生变化。接下来再把这个新的向量赋值给x。
这一结果看似已经改变了x中存储的向量,但实际上创建了新的向量并把它存储到x。这样的区别看上去可能微乎其微,但它是有影响的。例如,在某些情况下,它可能限制R的快速执行的潜力,这一问题将在后续学习。
- 获取向量长度
可以使用函数length()获得向量的长度。
>length()
- 作为向量的矩阵和数组
数组和矩阵(在某种意义上说,甚至包括列表)实际上都是向量。只不过它们还有额外的类属性。
> m<-rbind(c(1,4),c(2,2))
> m
[,1] [,2]
[1,] 1 4
[2,] 2 2
> m+10:13
[,1] [,2]
[1,] 11 16
[2,] 13 15
这里2×2的矩阵m按列存储为一个四元向量,即(1,3,2,4)。现在对它加上(10,11,12,13),得到向量(11,14,14,17),但最终如例子中的结果,R记得我们是对矩阵进行操作,因此返回2×2的矩阵。
- 声明
通常,编译语言要求你声明变量,即在使用前告诉编译器变量的存在。
和大多数的脚本语言(例如Python和Perl)一样,R中不需要声明变量。例如,下面这行代码:
>z<-2
这行代码前没有事先引用z,它完全是合法(并且普遍)的。
但是,如果要引用向量中特定的元素,就必须事先告知R。例如,我们希望y是一个二元向量,由5和12两元素构成
下面的语句无法正常工作:
>y[1]<-5
>y[2]<-12
Error in y[1] <- 5 : object ‘y’ not found
> y<-vector(length=2)
> y[1]<-5
> y[2]<-12
> y<-c(5,12)
这种方法同样正确,因为右边创建了一个新向量,然后绑定(bind)给变量y。
我们写R代码时,不能突然冒出诸如y[2]这样的语句,其原因归咎于R这种函数式语言的特性。在函数式语言中,读写向量中的元素,实际上由函数来完成。如果R事先不知道y是一个向量,那么函数将没有执行的对象。
对于绑定,由于变量没有事先声明,则它们的类型不受限制。以下一系列操作完全是有效的:
> x<-c(1,5)
> x
[1] 1 5
> x<"abc"
[1] TRUE TRUE
> x<-"abc"
x先被绑定为一个数值型向量,然后被绑定为字符串变量。(再次提醒C或C++背景的程序员,x只是一个指针,在不同的时间可以指向不同类型的对象。)
- 循环补齐
在对两个向量使用运算符时,如果要求这两个向量具有相同的长度,R会自动循环补齐(recycle),即重复较短的向量,直到它与另一个向量长度相匹配。下面是一个例子:
> c(1,2,4)+c(6,0,9,20,22)
[1] 7 2 13 21 24
Warning message:
In c(1, 2, 4) + c(6, 0, 9, 20, 22) :
longer object length is not a multiple of shorter object length
例子中较短的向量被循环补齐,因此运算其实是像下面这样执行的:
> c(1,2,4,1,2)+c(6,0,9,20,22)
[1] 7 2 13 21 24
下面是一个更为巧妙的例子:
> x<-rbind(c(1,4),c(2,5),c(3,6))
> x
[,1] [,2]
[1,] 1 4
[2,] 2 5
[3,] 3 6
> x+c(1,2)
[,1] [,2]
[1,] 2 6
[2,] 4 6
[3,] 4 8
矩阵实际上是个长向量
在这里,3×2的矩阵x是一个六元向量,它在R中一列一列的存储。换句话说,在存储方面,x与c(1,2,3,4,5,6)相同。我们把二元向量c(1,2)加到这个六元向量上,则所加的二元向量要再重复两次才能变成六个元素。换句话说,实际的运算如下:
> x+c(1,2,1,2,1,2)
[,1] [,2]
[1,] 2 6
[2,] 4 6
[3,] 4 8
不仅如此,在相加之前,c(1,2,1,2,1,2)在形式上也由向量转变为与x相同维数的矩阵,即:
1 2
2 1(为何是2 1,没想明白)
1 2
也就是说,最后结果是计算下面的式子:
好了,今天暂且到这儿吧~