S语言是基于对象的语言,不过它的最基本的数据还是一些类型,如向量、矩阵、列表(list)等。更复杂的数据用对象表示,比如,数据框对象,时间序列对象,模型对象,图形对象,等等。
S语言表达式可以使用常量和变量。变量名的规则是:由字母、数字、句点组成,第一个字符必须是字母,长度没有限制。大小写是不同的。特别要注意句点可以作为名字的合法部分,而在其它面向对象语言中句点经常用来分隔对象与成员名。另外,下划线不能用在名字中,因为它是赋值符号“<-”的缩写。
常量可以笼统地分为逻辑型、数值型和字符型三种,实际上数值型数据又可以分为整型、单精度、双精度等,非特殊需要不必太关心其具体类型。例如,123,123.45,1.2345e30 是数值型常量,"Weight","李明"是字符型(用两个双撇号或两个单撇号包围)。逻辑真值写为T或TRUE(注意区分大小写,写t或true都没意义),逻辑假值写为F或FALSE。复数常量就用3.5-2.1i这样的写法表示。
S中的数据可以取缺失值,用符号NA代表缺失值。函数is.na(x)返回x是否缺失值(真还是假)。
向量是具有相同基本类型的元素序列,大体相当于其他语言中的一维数组。实际上在S 中标量也被看作是长度为1的向量。
定义向量的最常用办法是使用函数c(),它把若干个数值或字符串组合为一个向量,比如: > marks <- c(10, 6, 4, 7, 8) > x <- c(1:3, 10:13) > x [1] 1 2 3 10 11 12 13 > x1 <- c(1, 2) > x2 <- c(3, 4) > x <- c(x1, x2) > x [1] 1 2 3 4
在显示向量值时我们注意到左边总出现一个“[1]”,这是代表该显示行的第一个数的下标,例如:
> 1234501:1234520
[1] 1234501 1234502 1234503 1234504 1234505 1234506 1234507 1234508 1234509 1234510
[11] 1234511 1234512 1234513 1234514 1234515 1234516 1234517 1234518 1234519 1234520
第二行输出从第11个数开始,所以在行左边显示“[11]”。
S中用符号“<-”(这是小于号紧接一个减号)来为变量赋值。另一种赋值的办法是用assign函数,比如
> x1 <- c(1, 2)和
> assign("x1", c(1, 2))效果相同。
函数length(x)可以计算向量x的长度。
可以对向量进行加(+)减(-)乘(*)除(/)、乘方(^)运算,其含意是对向量的每一个元素进行运算。;例如:
> x <- c(1, 4, 6.25) > y <- x*2+1 > y [1] 3.0 9.0 13.5另外,%/%表示整数除法(比如5 %/% 3为1),%%表示求余数(如5 %% 3为2)。
也可以用向量作为函数自变量,sqrt、log、exp、sin、cos、tan等函数都可以用向量作自变量,结果是对向量的每一个元素取相应的函数值,如:
> sqrt(x) [1] 1.0 2.0 2.5
函数min和max分别取自变量向量的最小值和最大值,函数sum计算自变量向量的元素和,函数mean计算均值,函数var计算样本方差,函数sd计算标准差(在Splus中用sqrt(var())计算),函数range返回包含两个值的向量,第一个值是最小值,第二个值是最大值。例如:
> max(x) [1] 6.25
如果求var(x)而x是 矩阵,则结果为样本协方差阵。
sort(x)返回x的元素从小到大排序的结果向量。order(x)返回使得x从小到大排列的元素下标向量(x[order(x)]等效于order(x))。
任何数与缺失值的运算结果仍为缺失值。例如,
> 2*c(1, NA, 2) [1] 2 NA 4 > sum(c(1, NA, 2)) [1] NA
在S中很容易产生一个等差数列。例如,1:n产生从1到n的整数列,-2:3产生从-2到3 的整数列,5:2产生反向的数列:
> n <- 5 > 1:n [1] 1 2 3 4 5 > -2:3 [1] -2 -1 0 1 2 3 > 5:2 [1] 5 4 3 2 要注意1:n-1不是代表1到n-1而是向量1:n减去1,这是一个常犯的错误: > 1:n-1 [1] 0 1 2 3 4 > 1:(n-1) [1] 1 2 3 4
seq函数是更一般的等差数列函数。如果只指定一个自变量n>0,则seq(n)相当于1:n 。指定两个自变量时,第一自变量是开始值,第二自变量是结束值,如seq(-2,3)是从-2到3 。S函数调用的一个很好的特点是它可以使用不同个数的自变量,函数可以对不同类型的自变量给出不同结果,自变量可以用“自变量名=自变量值”的形式指定。例如,seq(-2,3)可以写成seq(from=-2, to=3)。可以用一个by参数指定等差数列的增加值,例如:
> seq(0, 2, 0.7) [1] 0.0 0.7 1.4 也可以写成seq(from=0, to=2, by=0.7)。有参数名的参数的次序任意,如: > seq(0, by=0.7, to=2) [1] 0.0 0.7 1.4
可以用length参数指定数列长度,如seq(from=10, length=5)产生10到14。seq函数还可以用一种seq(along=向量名)的格式,这时只能用这一个参数,产生该向量的下标序列,如:
> x [1] 1.00 4.00 6.25 > seq(along=x) [1] 1 2 3 另一个类似的函数是rep,它可以重复第一个自变量若干次,例如: > rep(x,3) [1] 1.00 4.00 6.25 1.00 4.00 6.25 1.00 4.00 6.25 第一个参数名为x,第二个参数名为times(重复次数)。
> l <- c(T, T, F) > l [1] TRUE TRUE FALSE当然,逻辑向量是一个比较的结果,如:
> x [1] 1.00 4.00 6.25 > l <- x > 3 > l [1] FALSE TRUE TRUE一个向量与常量比较大小,结果还是一个向量,元素为每一对比较的结果逻辑值。两个向量也可以比较,如:
> log(10*x) [1] 2.302585 3.688879 4.135167 > log(10*x) > x [1] TRUE FALSE FALSE比较运算符包括<,<=,>,>=,==(相等),!=(不等)。
两个逻辑向量可以进行与(&)、或(|)运算,结果是对应元素运算的结果。对逻辑向量x计算!x表示取每个元素的非。例如:
> (x > 1.5) & log(10*x)>1.5 [1] FALSE FALSE TRUE判断一个逻辑向量是否都为真值的函数是all,如:
> all(log(10*x) > x) [1] FALSE判断是否其中有真值的函数是any,如:
> any(log(10*x) > x) [1] TRUE函数is.na(x)用来判断x的每一个元素是否缺失。如
> is.na(c(1, NA, 3)) [1] FALSE TRUE FALSE
&# 9;逻辑值可以强制转换为整数值,TRUE变成1,FALSE变成0。例如,我们以age>65为老年人,否则为年轻人,可以用c("young", "old")[(age>65)+1]这样的表示。当年龄大于65时age>65等于TRUE,加1则把TRUE转换为数值型的1,结果得2,于是返回第二个下标处的“old”。否则等于0+1下标处的“young”。
> c1 <- c("x", "sin(x)") > c1 [1] "x" "sin(x)" > ns <- c("Weight", "Height", "年龄") > ns [1] "Weight" "Height" "年龄" paste函数用来把它的自变量连成一个字符串,中间用空格分开,例如: > paste("My", "Job") [1] "My Job"
连接的自变量可以是向量,这时各对应元素连接起来,长度不相同时较短的向量被重复使用。自变量可以是数值向量,连接时自动转换成适当的字符串表示,例如:
> paste(c("X", "Y"), "=", 1:4) [1] "X = 1" "Y = 2" "X = 3" "Y = 4"分隔用的字符可以用sep参数指定,例如下例产生若干个文件名:
> paste("result.", 1:6, sep="") [1] "result.1" "result.2" "result.3" "result.4" "result.5" "result.6"
如果给paste()函数指定了collapse参数,则paste()可以把一个字符串向量的各个元素连接成一个字符串,中间用collapse指定的值分隔。比如paste(c('a', 'b'), collapse='.') 得到'a.b'。
S支持复数运算。复数常量只要用3.5+2.1i这样的格式即可。复向量的每一个元素都是复数。可以用complex()函数生成复向量(见帮助)。Re()计算实部,Im()计算虚部,Mod() 计算复数模,Arg()计算复数幅角。
S提供了十分灵活的访问向量元素和向量子集的功能。某一个元素只要用x[i]的格式访问,其中x是一个向量名,或一个取向量值的表达式,如:
> x [1] 1.00 4.00 6.25 > x[2] [1] 4 > (c(1, 3, 5) + 5)[2]
[1] 8
可以单独改变一个元素的值,例如:
> x[2] <- 125 > x [1] 1.00 125.00 6.25
事实上,S提供了四种方法来访问向量的一部分,格式为x[v],x为向量或向量值的表达式,v是如下的表示下标向量:
v为一个向量,取值在1到length(x)之间,取值允许重复,例如,
> x[c(1,3)] [1] 1.00 6.25 > x[1:2] [1] 1 125 > x[c(1,3,2,1)] [1] 1.00 6.25 125.00 1.00 > c("a", "b", "c")[rep(c(2,1,3), 3)] [1] "b" "a" "c" "b" "a" "c" "b" "a" "c"
v为一个向量,取值在-length(x)到-1之间,表示扣除相应位置的元素。例如:
> x[-(1:2)]
[1] 6.25
v为和x等长的逻辑向量,x[v]表示取出所有v为真值的元素,如:
> x [1] 1.00 125.00 6.25 > x<10 [1] TRUE FALSE TRUE > x[x<10] [1] 1.00 6.25 > x[x<0] numeric(0)
可见x[x<10]取出所有小于10的元素组成的子集。这种逻辑值下标是一种强有力的检索工具,例如x[sin(x)>0]可以取出x中所有正弦函数值为正的元素组成的向量。
如果下标都是假值则结果是一个零长度的向量,显示为numeric(0)。
在定义向量时可以给元素加上名字,例如:
> ages <- c(Li=33, Zhang=29, Liu=18) > ages Li Zhang Liu 33 29 18
这样定义的向量可以用通常的办法访问,另外还可以用元素名字来访问元素或元素子集,例如:
> ages["Zhang"] Zhang 29 > ages[c("Li", "Liu")] Li Liu 33 18
向量元素名可以后加,例如:
> ages1 <- c(33, 29, 18) > names(ages1) <- c("Li", "Zhang", "Liu") > ages1 Li Zhang Liu 33 29 18
上面我们看到了如何访问向量的部分元素。在S中还可以改变一部分元素的值,例如:
> x [1] 1.00 125.00 6.25 > x[c(1,3)] <- c(144, 169) > x [1] 144 125 169
注意赋值的长度必须相同,例外是可以把部分元素赋为一个统一值:
> x[c(1,3)] <- 0 > x [1] 0 125 0
要把向量所有元素赋为一个相同的值而又不想改变其长度,可以用x[]的写法:
> x[] <- 0
注意这与“x <- 0”是不同的,前者赋值后向量长度不变,后者使向量变为标量0。
改变部分元素值的技术与逻辑值下标方法结合可以定义向量的分段函数,例如,要定义y=f(x)为当x<0时取1-x,否则取1+x,可以用:
> y <- numeric(length(x)) > y[x<0] <- 1 - x[x<0] > y[x>=0] <- 1 + x[x>0]