R语言数据处理分析实例

R Training
r
Author
Published

Thursday, February 6, 2020

前言

R是一种块状结构程序语言,“块”由大括号划分,当“块”只包含一条语句时大括号可以省略。程序语句由换行符或分号分隔。和许多脚本语言一样,R语言不需要“声明”变量。

接下来我们一起来处理分析一个简单的数据任务。

实例

一组学生参加了数学、科学和英语三科考试。为了给所有学生确定一个综合的成绩衡量指标,需要将这些科目的成绩组合起来,将排名在前20%的学生评定为A,接下来20%的学生评定为B,依此类推,最后,按字母顺序对学生进行排序。请试处理分析。

如下,我们首先创建原始数据框:

studentname= 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)
scoredata= data.frame(studentname, math, science, English, stringsAsFactors=FALSE)
scoredata
         studentname math science English
1         John Davis  502      95      25
2    Angela Williams  600      99      22
3   Bullwinkle Moose  412      80      18
4        David Jones  358      82      15
5  Janice Markhammer  495      75      20
6     Cheryl Cushing  512      85      28
7     Reuven Ytzrhak  410      80      15
8          Greg Knox  625      95      30
9       Joel England  573      89      27
10      Mary Rayburn  522      86      18

观察此数据集,马上可以发现一些明显的挑战:首先,三科考试成绩是无法比较的。由于它们的均值和标准差相差很大,对它们求三科的平均成绩是没有意义的。因此,在组合这些考试成绩之前,必须将其转换为可比较的成绩。

因而,我们做如下处理,将三科成绩进行标准化,这样每科考试成绩都是用单位标准差来表示,而非原始的分值尺度表示:

z= scale(scoredata[2:4])
z
             math     science     English
 [1,]  0.01269128  1.07806562  0.58685145
 [2,]  1.14336936  1.59143020  0.03667822
 [3,] -1.02568654 -0.84705156 -0.69688609
 [4,] -1.64871324 -0.59036927 -1.24705932
 [5,] -0.06807144 -1.48875728 -0.33010394
 [6,]  0.12806660 -0.20534583  1.13702468
 [7,] -1.04876160 -0.84705156 -1.24705932
 [8,]  1.43180765  1.07806562  1.50380683
 [9,]  0.83185601  0.30801875  0.95363360
[10,]  0.24344191 -0.07700469 -0.69688609
attr(,"scaled:center")
   math science English 
  500.9    86.6    21.8 
attr(,"scaled:scale")
     math   science   English 
86.673654  7.791734  5.452828 

scale函数为数据对象按列进行中心化(center=TRUE)或标准化(center=TRUE, scale=TRUE),默认情况下,函数scale对矩阵或数据框的指定列进行均值为0、标准差为1的标准化,给出各科成绩标准化后的结果以及各科成绩的均值和标准差。

然后,我们通过mean函数来计算各行的均值以获得三科成绩的综合评价得分,并使用cbind函数将其添加到学生成绩的原始数据框中:

Score= apply(z, 1, mean)
Score
 [1]  0.5592028  0.9238259 -0.8565414 -1.1620473 -0.6289776  0.3532485
 [7] -1.0476242  1.3378934  0.6978361 -0.1768163
scoredata2= cbind(scoredata, Score)
scoredata2
         studentname math science English      Score
1         John Davis  502      95      25  0.5592028
2    Angela Williams  600      99      22  0.9238259
3   Bullwinkle Moose  412      80      18 -0.8565414
4        David Jones  358      82      15 -1.1620473
5  Janice Markhammer  495      75      20 -0.6289776
6     Cheryl Cushing  512      85      28  0.3532485
7     Reuven Ytzrhak  410      80      15 -1.0476242
8          Greg Knox  625      95      30  1.3378934
9       Joel England  573      89      27  0.6978361
10      Mary Rayburn  522      86      18 -0.1768163

apply函数可将一个任意函数应用到矩阵、数组、数据框的任何维度上,在矩阵或数据框中,1表示行,2表示列。cbind函数进行列合并,增加列。

接下来,我们通过函数quantile给出三科成绩综合评价得分的百分位数,将学生的百分位数排名重编码为一个新的类别型成绩变量grade,如下:

y= quantile(Score, c(0.8,0.6,0.4,0.2))
y
       80%        60%        40%        20% 
 0.7430341  0.4356302 -0.3576808 -0.8947579 
scoredata2$grade[Score >=y[1]]= "A"
scoredata2$grade[Score < y[1] & Score >=y[2]]= "B"
scoredata2$grade[Score < y[2] & Score >=y[3]]= "C"
scoredata2$grade[Score < y[3] & Score >=y[4]]= "D"
scoredata2$grade[Score < y[4]]= "E"
scoredata2
         studentname math science English      Score grade
1         John Davis  502      95      25  0.5592028     B
2    Angela Williams  600      99      22  0.9238259     A
3   Bullwinkle Moose  412      80      18 -0.8565414     D
4        David Jones  358      82      15 -1.1620473     E
5  Janice Markhammer  495      75      20 -0.6289776     D
6     Cheryl Cushing  512      85      28  0.3532485     C
7     Reuven Ytzrhak  410      80      15 -1.0476242     E
8          Greg Knox  625      95      30  1.3378934     A
9       Joel England  573      89      27  0.6978361     B
10      Mary Rayburn  522      86      18 -0.1768163     C

quantile函数求分位数,这里求Score数值型向量的20%、40%、60%和80%分位点。

接下来,我们使用strsplit函数以空格把学生姓名拆分为姓氏和名字:

name= strsplit(scoredata2$studentname, " ")
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"
lastname= sapply(name, "[", 2)
firstname= sapply(name, "[", 1)
scoredata3= cbind(firstname, lastname, scoredata2[-1])
scoredata3
    firstname   lastname math science English      Score grade
1        John      Davis  502      95      25  0.5592028     B
2      Angela   Williams  600      99      22  0.9238259     A
3  Bullwinkle      Moose  412      80      18 -0.8565414     D
4       David      Jones  358      82      15 -1.1620473     E
5      Janice Markhammer  495      75      20 -0.6289776     D
6      Cheryl    Cushing  512      85      28  0.3532485     C
7      Reuven    Ytzrhak  410      80      15 -1.0476242     E
8        Greg       Knox  625      95      30  1.3378934     A
9        Joel    England  573      89      27  0.6978361     B
10       Mary    Rayburn  522      86      18 -0.1768163     C

strsplit函数应用到一个字符串向量上会返回一个列表,使用sapply函数分别提取列表中每个成分的第一个元素和第二个元素,[是一个可以提取某个对象的一部分的函数,再使用cbind函数将它们添加到学生成绩的原始数据中。

最后,我们使用order函数依姓氏和名字对数据集进行排序,完成这个数据任务。

scoredata4= scoredata3[order(lastname, firstname),]
scoredata4
    firstname   lastname math science English      Score grade
6      Cheryl    Cushing  512      85      28  0.3532485     C
1        John      Davis  502      95      25  0.5592028     B
9        Joel    England  573      89      27  0.6978361     B
4       David      Jones  358      82      15 -1.1620473     E
8        Greg       Knox  625      95      30  1.3378934     A
5      Janice Markhammer  495      75      20 -0.6289776     D
3  Bullwinkle      Moose  412      80      18 -0.8565414     D
10       Mary    Rayburn  522      86      18 -0.1768163     C
2      Angela   Williams  600      99      22  0.9238259     A
7      Reuven    Ytzrhak  410      80      15 -1.0476242     E