R語言(入門小練習篇)
阿新 • • 發佈:2019-01-29
問題:
一組學生參加了數學、科學和英語考試。為了給所有的學生確定一個單一的成績衡量指標,需要將這些科目的成績組合起來。另外,還想將前20%的學生評定為A,接下來20%的學生評定為B,以此類推。最後,希望按字母順序對學生排序。
Excel中的資料表(自己一個個敲的,最討厭做的事情TT)
StuId | StuName | Math | Science | English |
1 | John Davis | 502 | 95 | 25 |
2 | Angela Williams | 465 | 67 | 12 |
3 | Bull Jones | 621 | 78 | 22 |
4 | Cheryl Cushing | 575 | 66 | 18 |
5 | Reuven Ytzrhak | 454 | 96 | 15 |
6 | Joel Knox | 634 | 89 | 30 |
7 | Mary Rayburn | 576 | 78 | 37 |
8 | Greg England | 421 | 56 | 12 |
9 | Brad Tmac | 599 | 68 | 22 |
10 | Tracy Mcgrady | 666 | 100 | 38 |
step1:輸入資料——R語言匯入xlsx
1 #1資料輸入 2 install.packages("xlsx") 3 library(xlsx) 4 workbook<-"D:/R語言/code/R語言實戰前五章小試身手/StuScore.xlsx"#也可用‘\\’注意轉義字元 5 StuScore<-read.xlsx(workbook,1)#1表示sheet1 6 StuScore
step2:資料預處理——將變數進行標準化
因為數學,科學和英語考試的分值不同(均值和標準差均有較大差異),在組合之前要讓他們變得可以比較
方法:變數標準化,把每科成績都用單位標準差表示
tips:
所謂資料的標準化是指中心化之後的資料在除以資料集的標準差,即資料集中的各項資料減去資料集的均值再除以資料集的標準差。 例如有資料集1, 2, 3, 6, 3,其均值為3,其標準差為1.87,那麼標準化之後的資料集為(1-3)/1.87,(2-3)/1.87,(3-3)/1.87,(6-3)/1.87,(3-3)/1.87,即:-1.069,-0.535,0,1.604,0 資料中心化和標準化的意義是一樣的,為了消除量綱對資料結構的影響。
這裡使用scale()可以直接實現
1 > #2資料預處理 2 > options(digits=2)#限定為2位小數 3 > afterscale<-scale(StuScore[,3:5]) 4 > afterscale 5 Math Science English 6 [1,] -0.58 1.040 0.20 7 [2,] -1.02 -0.815 -1.17 8 [3,] 0.82 -0.086 -0.12 9 [4,] 0.28 -0.881 -0.54 10 [5,] -1.15 1.106 -0.86 11 [6,] 0.98 0.643 0.73 12 [7,] 0.29 -0.086 1.47 13 [8,] -1.54 -1.544 -1.17 14 [9,] 0.56 -0.749 -0.12 15 [10,] 1.35 1.372 1.57 16 attr(,"scaled:center") 17 Math Science English 18 551 79 23 19 attr(,"scaled:scale") 20 Math Science English 21 84.7 15.1 9.5
這裡,有兩個疑問:
1.說好的輸出兩位小數呢?Science那一欄輸出的都是三位小數,怎麼回事?
2.這是什麼東東?
-
1 attr(,"scaled:center") 2 Math Science English 3 551 79 23 4 attr(,"scaled:scale") 5 Math Science English 6 84.7 15.1 9.5
scale方法中的兩個引數center和scale的解釋:
1.center和scale預設為真,即T或者TRUE
2.center為真表示資料中心化
3.scale為真表示資料標準化
也就是說:center表示一列資料的均值,scale則表示標準差(有興趣的同學,可以用Excel的STDEV函式驗證一下)
step3:通過函式mean()來計算各行的均值以及獲得綜合得分,並使用cbind()將其新增到花名冊中
1 > #3在afterscale中計算標準差均值,並將其新增到StuScore 2 > score<-apply(afterscale,1,mean)#1表示行,mean表示均值函式 3 > StuScore<-cbind(StuScore,score) 4 > StuScore 5 StuId StuName Math Science English score 6 1 1 John Davis 502 95 25 0.22 7 2 2 Angela Williams 465 67 12 -1.00 8 3 3 Bull Jones 621 78 22 0.21 9 4 4 Cheryl Cushing 575 66 18 -0.38 10 5 5 Reuven Ytzrhak 454 96 15 -0.30 11 6 6 Joel Knox 634 89 30 0.78 12 7 7 Mary Rayburn 576 78 37 0.56 13 8 8 Greg England 421 56 12 -1.42 14 9 9 Brad Tmac 599 68 22 -0.10 15 10 10 Tracy Mcgrady 666 100 38 1.43
Step4:函式quantile()給出學生綜合得分的百分位數
quantile(x,probs):求分位數,其中x為待求分位數的數值型向量,probs為一個由[0,1]之間的概率值組成的數值向量
1 > afterquantile<-quantile(score,c(.8,.6,.4,.2)) 2 > afterquantile 3 80% 60% 40% 20% 4 0.60 0.21 -0.18 -0.50
step5:使用邏輯運算子,把score轉為等級(離散型)
1 > #5使用邏輯運算子,把score轉為等級(離散型) 2 > StuScore$grade[score>=afterquantile[1]]<-"A" 3 > StuScore$grade[score<afterquantile[1]&&score>=afterquantile[2]]<-"B" 4 > StuScore$grade[score<afterquantile[2]&&score>=afterquantile[3]]<-"C" 5 > StuScore$grade[score<afterquantile[3]&&score>=afterquantile[4]]<-"D" 6 > StuScore$grade[score<afterquantile[4]]<-"E" 7 > StuScore 8 StuId StuName Math Science English score grade 9 1 1 John Davis 502 95 25 0.22 B 10 2 2 Angela Williams 465 67 12 -1.00 E 11 3 3 Bull Jones 621 78 22 0.21 B 12 4 4 Cheryl Cushing 575 66 18 -0.38 E 13 5 5 Reuven Ytzrhak 454 96 15 -0.30 E 14 6 6 Joel Knox 634 89 30 0.78 B 15 7 7 Mary Rayburn 576 78 37 0.56 B 16 8 8 Greg England 421 56 12 -1.42 E 17 9 9 Brad Tmac 599 68 22 -0.10 E 18 10 10 Tracy Mcgrady 666 100 38 1.43 B
Step6:使用strsplit()以空格為界把學生姓名拆分為姓氏和名字
1 > #Step6:使用strsplit()以空格為界把學生姓名拆分為姓氏和名字 2 > name<-strsplit((StuScore$StuName)," ") 3 Error in strsplit((StuScore$StuName), " ") : non-character argument 4 > name 5 [1] "Jim" "Tony" "Lisa" "Tom"
這裡出錯了,原因很明確,沒有字元型的引數傳入,反應過來,原來是用execl匯入的時候,StuName那一列預設的是什麼型別的呢?我們來檢測一下
1 > is.numeric(StuScore$StuName) 2 [1] FALSE 3 > is.logical(StuScore$StuName) 4 [1] FALSE 5 > is.character(StuScore$StuName) 6 [1] FALSE 7 > is.complex(StuScore$StuName) 8 [1] FALSE 9 > help(type) 10 > typeof(StuScore$StuName) 11 [1] "integer"
因此,我們把他改為字元型
1 > #Step6:使用strsplit()以空格為界把學生姓名拆分為姓氏和名字 2 > StuScore$StuName<-as.character(StuScore$StuName) 3 > is.character(StuScore$StuName) 4 [1] TRUE 5 > name<-strsplit(StuScore$StuName," ") 6 > name 7 [[1]] 8 [1] "John" "Davis" 9 10 [[2]] 11 [1] "Angela" "Williams" 12 13 [[3]] 14 [1] "Bull" "Jones" 15 16 [[4]] 17 [1] "Cheryl" "Cushing" 18 19 [[5]] 20 [1] "Reuven" "Ytzrhak" 21 22 [[6]] 23 [1] "Joel" "Knox" 24 25 [[7]] 26 [1] "Mary" "Rayburn" 27 28 [[8]] 29 [1] "Greg" "England" 30 31 [[9]] 32 [1] "Brad" "Tmac" 33 34 [[10]] 35 [1] "Tracy" "Mcgrady"
Step7:把name分成Firstname和LastName,加入到StuScore中
1 > #7把name分成Firstname和LastName,加入到StuScore中 2 > FirstName<-sapply(name,"[",1) 3 > LastName<-sapply(name,"[",2) 4 > StuScore<-cbind(FirstName,LastName,StuScore[,-1]) 5 > StuScore 6 FirstName LastName LastName StuName Math Science English score grade 7 1 John Davis Davis John Davis 502 95 25 0.22 B 8 2 Angela Williams Williams Angela Williams 465 67 12 -1.00 E 9 3 Bull Jones Jones Bull Jones 621 78 22 0.21 B 10 4 Cheryl Cushing Cushing Cheryl Cushing 575 66 18 -0.38 E 11 5 Reuven Ytzrhak Ytzrhak Reuven Ytzrhak 454 96 15 -0.30 E 12