一. R的数学函数,统计函数及字符处理函数

例01:一道实际应用题

一组学生其数学,科学和英语的成绩如下表:

Chapter 05—Advanced data management(Part 1)-LMLPHP

任务:根据成绩,决定对每个学生的单独指导;

前20%的学生的成绩为A,次之为B,以此类推;

把学生姓名按照字母表顺序排序。

问题:三科考试的分数不具可比性;必须把考试分数转化为可以比较的记分单元,然后才能进行分数间的比较。

为分配A,B等级,需把学生成绩转换为百分比形式。

姓名有单独的域,使得分配学生的任务变得更难;故应该把名字分为名和姓。

1. 数字和字符函数(Numerical(mathematical+statistical+probability) and character functions)

(1)数学函数(mathematical functions)

Chapter 05—Advanced data management(Part 1)-LMLPHP

例02:常用的数学函数

> abs(-4)
[1] 4
> sqrt(25)
[1] 5
> ceiling(3.475)
[1] 4
> floor(5.99)
[1] 5
> trunc(5.99)
[1] 5
> round(3.475,digits=2)
[1] 3.48
> signif(3.475,digits=2)
[1] 3.5
> cos(60)
[1] -0.952413
> sin(60)
[1] -0.3048106
> tan(60)
[1] 0.3200404
> acos(-0.952413)
[1] 2.831853
> asin(-0.3048106)
[1] -0.3097396
> atan(0.3200404)
[1] 0.3097396
> cosh(2)
[1] 3.762196
> sinh(2)
[1] 3.62686
> tanh(2)
[1] 0.9640276
> acosh(3.762196)
[1] 2
> asinh(3.62686)
[1] 2
> atanh(0.9640276)
[1] 2
> log10(10)
[1] 1
> log(10)
[1] 2.302585
> exp(2.3026)
[1] 10.00015

(2)统计函数(statistical functions)

Chapter 05—Advanced data management(Part 1)-LMLPHP

Chapter 05—Advanced data management(Part 1)-LMLPHP

例03:常用的统计函数

> mean(c(1,2,3,4))
[1] 2.5
> median(c(1,2,3,4))
[1] 2.5
> sd(c(1,2,3,4))
[1] 1.290994
> var(c(1,2,3,4))
[1] 1.666667
> mad(c(1,2,3,4))
[1] 1.4826
> x<-c(1,2,3,4)
> range(x)
[1] 1 4
> diff(range(x))
[1] 3
> > sum(1,2,3,4)
[1] 10
> > x<-c(1,5,23,29)
> diff(x)
[1] 4 18 6
> > min(c(1,2,3,4))
[1] 1
> max(c(1,2,3,4))
[1] 4

例04:计算平均值和标准差

> x<-c(1,2,3,4,5,6,7,8)
>
> mean(x)
[1] 4.5
> sd(x)
[1] 2.44949
>
> n<-length(x)
> meanx<-sum(x)/n
> css<-sum((x-meanx)^2)
> sdx<-sqrt(css/(n-1))
> meanx
[1] 4.5
> sdx
[1] 2.44949

A)为标准化每一列的暂定平均数(arbitrary mean)和标准差(standard deviation),可以使用下面格式的代码:

newdata<-scale(mydata)*SD+M

其中,M是期待的均值,SD是期待的标准差。

注意:scale()在非数值的列中使用,会产生错误。

B)标准化某一特定的列,而非一个矩阵或数据帧,则可以使用下面的代码:

newdata<-transform(mydata,myvar=scale(myvar)*10+50)

·标准化myvar,使其为一个平均值为50,标准差为10的变量。

(3)概率函数(probability functions)

在R中,概率函数的形式如下:

[dpqr]=distribution_abbreviation()

·d=dentity, p=distribution function, q=quantile function, r=random generation(random deviates)

常见的概率分布如下图:

Chapter 05—Advanced data management(Part 1)-LMLPHP

例05:从均匀分布产生一个随机数

·set.seed()函数:明确的指定种子,使求为随机数的结果,多次重复仍可得到;

·runif()函数:在均匀分布上,产生0到1之间的伪随机数。

> runif(5)
[1] 0.1476982 0.4830784 0.2800061 0.9300127 0.7477501
> runif(5)
[1] 0.6784092 0.9378730 0.1152914 0.5070802 0.1728310
> set.seed(1234)
> runif(5)
[1] 0.1137034 0.6222994 0.6092747 0.6233794 0.8609154
> set.seed(1234)
> runif(5)
[1] 0.1137034 0.6222994 0.6092747 0.6233794 0.8609154

例06:从多元正态分布中产生数据

mvnorm()函数:在MASS包中;从多元正态分布中取来自于平均值向量和协方差矩阵中取数据。

mvnorm(n,mean,sigma)

·n:希望的样例大小(desired sample size);

·mean:平均值的向量(mean vector);

·sigma:协方差矩阵(variance-covariance matrix)。

Chapter 05—Advanced data management(Part 1)-LMLPHP

> library(MASS)
> options(digits=3)
> set.seed(1234)
>
> mean<-c(230.7,146.7,3.6)
> sigma<-matrix(c(15360.8,6721.2,-47.1,6721.2,4700.9,-16.5,-47.1,-16.5,0.3),nrow=3,ncol=3)
>
> mydata<-mvrnorm(500,mean,sigma)
> mydata<-as.data.frame(mydata)
> names(mydata)<-c("y","x1","x2")
>
> dim(mydata)
[1] 500 3
> head(mydata,n=10)
y x1 x2
1 434.9 286.6 2.57
2 61.4 69.1 4.32
3 142.0 108.5 3.37
4 182.1 72.8 3.52
5 165.1 185.1 3.15
6 167.2 160.3 3.27
7 258.2 233.6 3.41
8 84.3 54.2 4.10
9 158.5 130.7 3.94
10 131.8 176.8 4.43
>

A)set.seed(1234):设置一个随机数种子;

B)特例化平均值向量为mean,协方差矩阵为sigma;

C)产生500个伪随机数的观测量(pseudo-random observations),用mydata保存;

D)为了方便,用dim()函数,把结果从矩阵转换为数据帧,并且用head()函数,为变量赋一个名字。

(4)字符函数(character functions)

数学函数和统计函数对数值型数据处理,字符函数对文本型数据进行处理。

Chapter 05—Advanced data management(Part 1)-LMLPHP

Chapter 05—Advanced data management(Part 1)-LMLPHP

例07:字符函数的小例子

> x<-c("ab","cde","fghij")
> length(x)
[1] 3
> nchar(x)
[1] 2 3 5
> nchar(x[3])
[1] 5
>
> x<-"abcdef"
> substr(x,2,4)
[1] "bcd"
> substr(x,2,4)<-"22222"
> x
[1] "a222ef"
>
> grep("A",c("b","A","c"),fixed=TRUE)
[1] 2
> > sub("\\s",".","Hello There")
[1] "Hello.There"
>
> y<-strsplit("abc","")
> y
[[1]]
[1] "a" "b" "c"

> paste("x",1:3,sep="")
[1] "x1" "x2" "x3"
> paste("x",1:3,sep="M")
[1] "xM1" "xM2" "xM3"
> paste("Today is",date())
[1] "Today is Thu Aug 01 08:03:33 2013"
>
> toupper("abc")
[1] "ABC"
>
> tolower("ABC")
[1] "abc"
>

(5)其他函数

Chapter 05—Advanced data management(Part 1)-LMLPHP

例08:其他函数的例子

> x<-c(2,5,6,9)
> length(x)
[1] 4
>
> indices<-seq(1,10,2)
> indices
[1] 1 3 5 7 9
>
> y<-rep(1:3,2)
> y
[1] 1 2 3 1 2 3
>
> firstname<-c("Jane")
> cat("Hello",firstname,"\n")
Hello Jane
>
> name<-"Bob"
> cat("Hello",name,"\b.\n","Isn\'t R","\t","GREAT?\n")
Hello Bob.
Isn't R GREAT?

例09:apply函数的例子

> mydata<-matrix(rnorm(30),nrow=6)
> mydata
[,1] [,2] [,3] [,4] [,5]
[1,] -1.70058013 -0.04791481 1.8256761 0.18096362 0.747712227
[2,] 0.61948876 0.08585212 1.0945512 0.37603502 0.002217611
[3,] 0.05312635 -0.22062291 -0.4759186 0.17347971 0.764638370
[4,] -0.72229860 0.58144854 -1.1961967 -0.07836057 0.342189978
[5,] -0.68587492 -0.93605640 -2.8959270 1.08664460 0.205011102
[6,] 0.10207794 -0.80774063 0.9329347 0.44210056 0.360341446
> apply(mydata,1,mean)
[1] 0.20117141 0.43562895 0.05894057 -0.21464346 -0.64524053 0.20594280
> apply(mydata,2,mean)
[1] -0.3890101 -0.2241723 -0.1191467 0.3634772 0.4036851
> apply(mydata,2,mean,trim=2)
[1] -0.3163743 -0.1342689 0.2285080 0.2784993 0.3512657
> apply(mydata,2,mean,trim=0.2)
[1] -0.31324231 -0.24760656 0.08884265 0.29314473 0.41381369

apply()函数:在数组的边缘使用一个函数;

lapply()函数,sapply()函数:对表使用一个函数。

apply(x,MARGIN,FUN,...)

·x:数据对象;

·MARGIN:索引的维度(dimension index);

·FUN:指定的函数;

·.......:传给函数的参数。

2. 例01的解决办法

(1)输入表中的数据

Chapter 05—Advanced data management(Part 1)-LMLPHP

> options(digits=2)
> Students<-c("John Davis","Angela Williams","Bullwinkle Moose","David Jones","Janice Markhammer","Cheryl Cushing","Reuven Ytzrhak","Greg Knox","Joel England","Mary Rayburn")
> Math<-c(502,600,412,358,495,512,410,625,573,522)
> Science<-c(95,99,80,82,75,85,80,95,89,86)
> English<-c(25,22,18,15,20,28,15,30,27,18)
> roster<-data.frame(Students,Math,Science,English,stringAsFactors=FALSE)
> roster
Students Math Science English stringAsFactors
1 John Davis 502 95 25 FALSE
2 Angela Williams 600 99 22 FALSE
3 Bullwinkle Moose 412 80 18 FALSE
4 David Jones 358 82 15 FALSE
5 Janice Markhammer 495 75 20 FALSE
6 Cheryl Cushing 512 85 28 FALSE
7 Reuven Ytzrhak 410 80 15 FALSE
8 Greg Knox 625 95 30 FALSE
9 Joel England 573 89 27 FALSE
10 Mary Rayburn 522 86 18 FALSE

options(digits=2):小数点后仅保留2位数字。

(2)因为数学,科学和英语都是用不同的范围来表示的,需使这三种成绩可以比较。一种较常用的方法就是:标准化变量,使数据表现为标准差的形式。scale()函数。

z<-scale(roster[,2:4])
> z
Math Science English
[1,] 0.013 1.078 0.587
[2,] 1.143 1.591 0.037
[3,] -1.026 -0.847 -0.697
[4,] -1.649 -0.590 -1.247
[5,] -0.068 -1.489 -0.330
[6,] 0.128 -0.205 1.137
[7,] -1.049 -0.847 -1.247
[8,] 1.432 1.078 1.504
[9,] 0.832 0.308 0.954
[10,] 0.243 -0.077 -0.697
attr(,"scaled:center")
Math Science English
501 87 22
attr(,"scaled:scale")
Math Science English
86.7 7.8 5.5

(3)通过计算每个同学的平均分,即每行的平均数,来衡量一个学生表现的好坏。用到mean()函数和cbind()函数。

> score<-apply(z,1,mean)
> score
[1] 0.56 0.92 -0.86 -1.16 -0.63 0.35 -1.05 1.34 0.70 -0.18
> roster<-cbind(roster,score)
> roster
Students Math Science English stringAsFactors score
1 John Davis 502 95 25 FALSE 0.56
2 Angela Williams 600 99 22 FALSE 0.92
3 Bullwinkle Moose 412 80 18 FALSE -0.86
4 David Jones 358 82 15 FALSE -1.16
5 Janice Markhammer 495 75 20 FALSE -0.63
6 Cheryl Cushing 512 85 28 FALSE 0.35
7 Reuven Ytzrhak 410 80 15 FALSE -1.05
8 Greg Knox 625 95 30 FALSE 1.34
9 Joel England 573 89 27 FALSE 0.70
10 Mary Rayburn 522 86 18 FALSE -0.18

(4)quantile()函数给出每个学生的表现分数的百分比的排名。

> y<-quantile(roster$score,c(.8,.6,.4,.2))
> y
80% 60% 40% 20%
0.74 0.44 -0.36 -0.89

(5)使用逻辑操作符,在一个新的成绩变量的分类中,这需要在数据帧roster添加新的变量grade。

> roster$grade[score>=y[1]]<-"A"
> roster$grade[score<y[1]&score>=y[2]]<-"B"
> roster$grade[score<y[2]&score>=y[3]]<-"C"
> roster$grade[score<y[3]&score>=y[4]]<-"D"
> roster$grade[score<y[4]]<-"F"
> roster
Students Math Science English stringAsFactors score grade
1 John Davis 502 95 25 FALSE 0.56 B
2 Angela Williams 600 99 22 FALSE 0.92 A
3 Bullwinkle Moose 412 80 18 FALSE -0.86 D
4 David Jones 358 82 15 FALSE -1.16 F
5 Janice Markhammer 495 75 20 FALSE -0.63 D
6 Cheryl Cushing 512 85 28 FALSE 0.35 C
7 Reuven Ytzrhak 410 80 15 FALSE -1.05 F
8 Greg Knox 625 95 30 FALSE 1.34 A
9 Joel England 573 89 27 FALSE 0.70 B
10 Mary Rayburn 522 86 18 FALSE -0.18 C

(6)使用strsplit()函数:让一个向量返回一个表。在此题中,把学生的名和姓的中间的空格符去掉。

> name<-strsplit(roster$Students," ")
Error in strsplit(roster$Students, " ") : non-character argument
> is.character(roster$character)
[1] FALSE
> name<-strsplit(as.character(roster$Students)," ")
> name
[[1]]
[1] "John" "Davis" [[2]]
[1] "Angela" "Williams" [[3]]
[1] "Bullwinkle" "Moose" [[4]]
[1] "David" "Jones" [[5]]
[1] "Janice" "Markhammer" [[6]]
[1] "Cheryl" "Cushing" [[7]]
[1] "Reuven" "Ytzrhak" [[8]]
[1] "Greg" "Knox" [[9]]
[1] "Joel" "England" [[10]]
[1] "Mary" "Rayburn"

(7)sapply()函数:提取每个组合的第一个元素,放在名的数组中;提取每个组合的第二个元素,放在姓的数组中。

cbind()函数:把姓和名的数组添加到roster中。

删除roster中的Students这一列。

Firstname<-sapply(name,"[",1)
> Lastname<-sapply(name,"[",2)
> roster<-cbind(Firstname,Lastname,roster[,-1])
> roster
Firstname Lastname Math Science English stringAsFactors score grade
1 John Davis 501 95 25 FALSE 0.56 B
2 Angela Williams 600 99 22 FALSE 0.92 A
3 Bullwinkle Moose 412 80 18 FALSE -0.86 D
4 David Jones 358 82 15 FALSE -1.16 F
5 Janice Markhammer 495 75 20 FALSE -0.63 D
6 Cheryl Cushing 512 85 28 FALSE 0.35 C
7 Reuven Ytzrhak 410 80 15 FALSE -1.05 F
8 Greg Knox 625 95 30 FALSE 1.34 A
9 Joel England 573 89 27 FALSE 0.70 B
10 Mary Rayburn 522 86 18 FALSE -0.18 C

(8)通过Firstname和Lastname排列数据集roster

> roster[order(Lastname,Firstname),]
Firstname Lastname Math Science English stringAsFactors score grade
6 Cheryl Cushing 512 85 28 FALSE 0.35 C
1 John Davis 501 95 25 FALSE 0.56 B
9 Joel England 573 89 27 FALSE 0.70 B
4 David Jones 358 82 15 FALSE -1.16 F
8 Greg Knox 625 95 30 FALSE 1.34 A
5 Janice Markhammer 495 75 20 FALSE -0.63 D
3 Bullwinkle Moose 412 80 18 FALSE -0.86 D
10 Mary Rayburn 522 86 18 FALSE -0.18 C
2 Angela Williams 600 99 22 FALSE 0.92 A
7 Reuven Ytzrhak 410 80 15 FALSE -1.05 F
05-11 15:01