第1章 R简介

1.2.4 向量化

1
2
3
4
> v<-c(4,7,23.5,67.2,80)
> x<-sqrt(v)
> x
[1] 2.000000 2.645751 4.847680 8.197561 8.944272

也可以使用R的这个热性进行向量的算术运算。

1
2
3
4
> v1<-c(4,6,87)
> v2<-c(34,32.4,12)
> v1+v2
[1] 38.0 38.4 99.0

如果两个向量的长度不同,R会自动的将较短的向量进行扩充。

1
2
3
4
> v1<-c(4,6,8,24)
> v2<-c(10,2)
> v1+v2
[1] 14 8 18 26

如果较长的向量的长度不是较短的向量的长度的整数倍,R将会给出警告,注意是警告而不是错误。

1
2
3
4
5
6
7
> v1<-c(4,6,8,24)
> v2<-c(10,2,4)
> v1+v2
[1] 14 8 12 34
Warning message:
In v1 + v2 :
longer object length is not a multiple of shorter object length

以上的内容是循环规则。

如前所述,单个数字在R中表示长度为1的向量。这种表示在下面的运算中非常方便:

1
2
3
> v1<-c(4,6,8,24)
> 2*v1
[1] 8 12 16 48

注意,数字2被循环,导致v1的所有元素都被乘以2,。正如我们将看到的,这种循环跪着也适用于其他对象,如数组和矩阵。

1.2.5 因子
因子提供了一个简单而又紧凑的形式来处理分类数据(名义)。因子用水平来表示所有可能的取值。如果数据集有取值个数固定的名义变量,因子就特别有用。R中的图形函数和汇总函数就是应用了因子的这种有点。对用户来说,这种使用和显示因子数据的方式显然是易于理解的,而R内部以数值编码的方式来存储因子值,这将大大提高内存的利用效率。

下面举个例子来说明如何在R中创建因子。假设有10个人的性别向量。

1
2
3
> g<-c("f","m","m","m","f","m","f","m","f","m","f","f")
> g
[1] "f" "m" "m" "m" "f" "m" "f" "m" "f" "m" "f" "f"

你可以把这个因子向量转为一个因子。

1
2
3
4
> g<-factor(g)
> g
[1] f m m m f m f m f m f f
Levels: f m

注意,这里得到的因子不再是一个字符向量。上面说到,实际上这些因子在R内部表示为数值向量。在这个例子中,因子有两个水平,fm,在R内部分别表示1和2.然而,我们不需要关系在内部是如何表示的,因为你可以使用原始的字符值,R在显示因子的时候,也使用这种字符方式。因此,出于效率的考虑,R因子的编码转换对用户是透明的。

假设另外有5个人,需要把他们的性别信息存储在另一个透明的因子对象中。假设他们都是男性。如果都仍然需要这个因子对象与对象g有两个相同的因子水平,则必须使用下面的命令。

1
2
3
4
> other.g<-factor(c("m","m","m","m","m"),levels = c("f","m"))
> other.g
[1] m m m m m
Levels: f m

如果没有在输入参数中设定level参数,因子other.g将只有一个水平(‘m’).

在R这样的函数式编程语言中,最常见的函数之一就是像上例中的函数复合。

利用因子类型的数据,可以做的一件事情就是计算每个可能值得发生次数。例如:

1
2
3
4
> table(g)
g
f m
6 6

1
2
3
4
> table(other.g)
other.g
f m
0 5

table也可以获取多个因子的交叉表。假设向量a存储10个人的所属的年龄,那么可以得到这两个向量的交叉表。如下:

1
2
3
4
5
6
7
8
9
10
11
12
> a<-factor(c('adult','adult','juvenile','juvenile','adult','adult','adult','juvenile','adult','juvenile'))
> length(a)
[1] 10
> length(g)
[1] 10
> g
[1] "f" "m" "m" "f" "m" "f" "m" "f" "m" "f"
> table(a,g)
g
a f m
adult 2 4
juvenile 3 1

如果数据过长的话,可以采用+进行换行输入。

1
2
3
4
5
> a<-factor(c('adult','adult','juvenile','juvenile','adult',
+ 'adult','adult','juvenile','adult','juvenile'))
> a
[1] adult adult juvenile juvenile adult adult adult juvenile adult juvenile
Levels: adult juvenile

有时候我们希望计算列联表的边际和相对频率。下面给出了上面数据集的性别和年龄因子的总计。

1
2
3
4
5
6
7
8
9
> t<-table(a,g)
> margin.table(t,1)
a
adult juvenile
6 4
> margin.table(t,2)
g
f m
5 5

输入参数12分别代表列联表的第一和第二个维度,即表示t的行和列。每个维度边际和总计的相对频率如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
> prop.table(t,1)
g
a f m
adult 0.3333333 0.6666667
juvenile 0.7500000 0.2500000
> prop.table(t,2)
g
a f m
adult 0.4 0.8
juvenile 0.6 0.2
> prop.table(t)
g
a f m
adult 0.2 0.4
juvenile 0.3 0.1

注意:如果需要的是百分比,可以在调用函数时乘以100

1
2
3
4
5
> 100*prop.table(t)
g
a f m
adult 20 40
juvenile 30 10

1.2.6 生产序列

R提供了狠多种生产不同类型序列的方法。比如:创建一个1~1000所有整数的向量,可以简单的输入

1
2
3
> x<-1:1000
> length(x)
[1] 1000

通过上面的语句就创建了一个名为x的向量,它包含了1000个元素。
注意运算符:的优先级,我们通过下面的例子来说明这个问题。

1
2
3
4
> 10:15-1
[1] 9 10 11 12 13 14
> 10:(15-1)
[1] 10 11 12 13 14

这里需要理解第一个命令的结果(记住循环规则),:的优先级高于减法-
同样,可以利用seq()生成实数序列。比如:

1
2
> seq(-4,1,0.5)
[1] -4.0 -3.5 -3.0 -2.5 -2.0 -1.5 -1.0 -0.5 0.0 0.5 1.0

生成了一个从-4到1的步长为0.5的一个实数序列。函数seq还有其他的功能。下面举例说明seq的其他功能。

1
2
3
4
5
6
seq(from=1,to=5,length=4)
[1] 1.000000 2.333333 3.666667 5.000000
> seq(from=1,to=5,length=2)
[1] 1 5
> seq(length=10,from = -2,by = 0.2)
[1] -2.0 -1.8 -1.6 -1.4 -1.2 -1.0 -0.8 -0.6 -0.4 -0.2

通过上面的例子,我们可以看到我们可以任意指定参数的顺序:但是要先给出参数名,再给出参数值。因此,当我们使用多个参数且大部分参数都采用默认值的函数时,这将非常方便。一旦这些默认参数能满足我们的要求,我们就可以避免人为的设置这些参数。

另一个产生具有某种模式序列的有用的函数时req()函数。比如:

1
2
3
4
5
6
7
8
> rep(5,10)
[1] 5 5 5 5 5 5 5 5 5 5
> rep("hi",3)
[1] "hi" "hi" "hi"
> rep(1:2,3)
[1] 1 2 1 2 1 2
> rep(1:2,each=3)
[1] 1 1 1 2 2 2

gl()函数可用于生成带有因子的序列。这个函数的语法是gl(k,n),其中k是因子水平的个数,n是每个每个因子水平的重复数。这里举两字例子:

1
2
3
4
5
6
> gl(3,5)
[1] 1 1 1 1 1 2 2 2 2 2 3 3 3 3 3
Levels: 1 2 3
> gl(2,5,labels=c('female','male'))
[1] female female female female female male male male male male
Levels: female male

最后R有多个可以根据不同概率密度函数来生成随机序列的函数。这些函数的通用结果是xfunc(n,par1,par2,...),其中,func是概率分布的名称,n是要生成的随机数的个数,par1,par2,...是概率密度函数所需要的一些参数值。例如,可以产生10个服从均值为0,标准差为1的正态分布的随机数值:

1
2
> rnorm(10)
[1] 1.29219470 -0.38849339 1.88505193 0.48227844 1.23505790 1.49568939 -1.14704749 -0.41806913 -0.09506815 0.73086971

为了获得5个服从自由度为10的t分布的随机变量,可以输入:

1
2
> rt(5, df = 10)
[1] 1.4049026 -0.5510834 0.1607854 1.4629028 -0.6332299

R还有很多其他的概率函数,以及其他获取概率密度、累计概率和这些分布的分位数函数。

1.2.7 数据子集

前面的例证提到,可以在方括号内放入元素的位置来获取向量的某个元素。R也允许在方括号中使用向量。R有很类型的索引向量。逻辑索引向量可以提取相应于真值的元素。

1
2
3
> x<-c(0,-3,4,-1,45,90,-5)
> x>0
[1] FALSE FALSE TRUE FALSE TRUE TRUE FALSE

上面显示的第二个命令是逻辑条件。由于x是向量,所以将向量中的所有的元素与0进行比较,产生一个长度与向量x相同的逻辑值向量。如果使用该逻辑值向量对x进行索引,就可以得到相应TRUE值位置的向量x的元素。

1
2
> x[x>0]
[1] 4 45 90

利用R中的逻辑运算符,可以使用更复杂的逻辑索引向量。如下:

1
2
3
4
> x[x<=2|x>5]
[1] 0 -3 -1 45 90 -5
> x[x>40&x<100]
[1] 45 90

上面都是简单的逻辑运算。就不再详细解释了。

R还可以使用整数向量来提取向量中的多个元素,索引向量中的数字表示提取的元素在原向量中的位置。例如:

1
2
3
4
5
6
7
8
9
> x
[1] 0 -3 4 -1 45 90 -5
> x[c(4,6)]
[1] -1 90
> x[1:3]
[1] 0 -3 4
> y<-c(1,4)
> x[y]
[1] 0 -1

另外可以使用一个负值的索引表示哪些元素可以排除。例如:

1
2
3
4
5
6
> x[-1]
[1] -3 4 -1 45 90 -5
> x[-c(4,6)]
[1] 0 -3 4 45 -5
> x[-(1:3)]
[1] -1 45 90 -5

这里-1表示删除第一个位置上的元素,其他的类似。

可以通过R函数names()来给向量中的元素命名,对于命名的向量元素,可以通过字符串向量来进行索引。由于命名的元素位置更容易进驻,所以有时候更名元素更受欢迎。例如,在5个不同的地方测量了一个化学参数的测量值向量。可以创建如下的命名空间:

1
2
3
4
5
6
7
8
9
> pH<-c(4.5,7,7.3,8.2,6.3)
> names(pH)<-c('area1','area2','mud','dam','middle')
> pH
area1 area2 mud dam middle
4.5 7.0 7.3 8.2 6.3
> table(pH)
pH
4.5 6.3 7 7.3 8.2
1 1 1 1 1

实际上,我们可以使用如下的方法进行创建。

1
2
3
4
5
6
7
> pH<-c(area1=4.5,area2=7, mud = 7.3, dam = 8.2, middle = 6.3)
> pH['middle']
middle
6.3
> pH[c('mud','middle')]
mud middle
7.3 6.3

1.2.8 矩阵和数组

数据元素可以保存在具有多个维度的对象中。在多种情况下这尤其有用,数组存储的是多维数据。矩阵是数组的特殊情况,它具有两个维度。在R中数组和矩阵都是带有维度这个属性的向量。假设一个数值向量c(45,23,66,77,33,44,56,12,78,23),下面要把这10个数值组织为一个矩阵:

1
2
3
4
5
6
7
8
> m<- c(45,23,66,77,33,44,56,12,78,23)
> m
[1] 45 23 66 77 33 44 56 12 78 23
> dim(m)<-c(2,5)
> m
[,1] [,2] [,3] [,4] [,5]
[1,] 45 66 33 56 78
[2,] 23 77 44 12 23

注意,数值如何分配到这2行5列的矩阵中。我们还可以使用更简单的命令:

1
2
3
4
5
> m<-matrix(c(45,23,66,77,33,44,56,12,78,23),2,5)
> m
[,1] [,2] [,3] [,4] [,5]
[1,] 45 66 33 56 78
[2,] 23 77 44 12 23

通过上面的这两个例子,我们注意到向量中的数据通过矩阵的列进行拓展。我们可以通过指定matrix的参数来指定向量以按行的方式进行拓展。

1
2
3
4
5
> m<-m<-matrix(c(45,23,66,77,33,44,56,12,78,23),2,5,byrow = T)
> m
[,1] [,2] [,3] [,4] [,5]
[1,] 45 23 66 77 33
[2,] 44 56 12 78 23

如矩阵的显示,我们可以通过类似以向量中的索引的方式来访问矩阵的元素。但是现在需要两个索引,因为矩阵至少是二维的。

1
2
> m[2,3]
[1] 12