R語言(入門小練習篇)
問題:
一組學生參加了數學、科學和英語考試。為了給所有的學生確定一個單一的成績衡量指標,需要將這些科目的成績組合起來。另外,還想將前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)," ")
3Error in strsplit((StuScore$StuName), " ") : non-character argument4 > 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 6 Joel Knox Knox Joel Knox 634 89 30 0.78 B
13 7 Mary Rayburn Rayburn Mary Rayburn 576 78 37 0.56 B
14 8 Greg England England Greg England 421 56 12 -1.42 E
15 9 Brad Tmac Tmac Brad Tmac 599 68 22 -0.10 E
16 10 Tracy Mcgrady Mcgrady Tracy Mcgrady 666 100 38 1.43 B
17 >
Step8:order排序
1 > #8order()排序
2 > StuScore[order(LastName,FirstName),]
3 FirstName LastName LastName StuName Math Science English score grade
4 4 Cheryl Cushing Cushing Cheryl Cushing 575 66 18 -0.38 E
5 1 John Davis Davis John Davis 502 95 25 0.22 B
6 8 Greg England England Greg England 421 56 12 -1.42 E
7 3 Bull Jones Jones Bull Jones 621 78 22 0.21 B
8 6 Joel Knox Knox Joel Knox 634 89 30 0.78 B
9 10 Tracy Mcgrady Mcgrady Tracy Mcgrady 666 100 38 1.43 B
10 7 Mary Rayburn Rayburn Mary Rayburn 576 78 37 0.56 B
11 9 Brad Tmac Tmac Brad Tmac 599 68 22 -0.10 E
12 2 Angela Williams Williams Angela Williams 465 67 12 -1.00 E
13 5 Reuven Ytzrhak Ytzrhak Reuven Ytzrhak 454 96 15 -0.30 E
14 >
雖然是照著書本上做的,但是,代碼必須要自己敲一遍,過程中遇到的一些小問題也解決了,就算菜鳥簡單入門。這樣樣例還可以繼續拓展,把R語言實戰前5章的內容盡可能用一邊,可以繪制一些圖,等等,本文還會繼續更新。
為ScienceScore繪制條形圖
根據不同的分數等級,顯示不同的顏色。
1 #為StuScore繪制分組條形圖
2 install.packages("vcd")
3 library(vcd)
4 fill_colors<-c() #不同的等級,不同的顏色顯示
5 for(i in 1:length(StuScore$Science)){
6 if(StuScore$Science[i]==100){
7 fill_colors<-c(fill_colors,"red")
8 }else if(StuScore$Science[i]<100&&StuScore$Science[i]>=80){
9 fill_colors<-c(fill_colors,"yellow")
10 }else if(StuScore$Science[i]<80&&StuScore$Science[i]>=60){
11 fill_colors<-c(fill_colors,"blue")
12 }else{
13 fill_colors<-c(fill_colors,"green")
14 }
15 }
16 barplot(StuScore$Science, #條形圖
17 main="Science Score",
18 xlab="Name",ylab="ScienceScore",
19 col=fill_colors,
20 names.arg=(paste(substr(FirstName,1,1),".",LastName)), #設定橫坐標名稱
21 border=NA, #條形框不設置邊界線
22 font.main=4,
23 font.lab=3,
24 beside=TRUE)
25 legend(x=8.8,y=100, #左上角點的坐標
26 cex=.8, #縮放比例
27 inset=5,
28 c("Excellent","Good","Ordinary","Bad"),
29 pch=c(15,16,17,19), #圖例中的符號
30 col=c("red","yellow","blue","green"),
31 bg="#821122", #背景色
32 xpd=TRUE, #可以在繪圖區之外顯示
33 text.font=8,
34 text.width=.6,
35 text.col=c("red","yellow","blue","green")
36 )
遇到的問題說明:
起初在設置了20行的名稱時,顯示了全名,因此出現了一下情況:
因為名稱太擠,顯示不出來。
解決辦法有三:
-
保存img時,增大像素值;
-
把名詞改為簡寫,即John Davis——>J.Davis
-
把名稱傾斜,與水平線呈一定的夾角
-
利用cex.names=.8對條形圖的表情進行微調(減小字號)
由于3沒有找到相應的設置參數,所以這里采用了第二種方法。
最后的效果圖:
CDA數據分析師考試相關入口一覽(建議收藏):
? 想報名CDA認證考試,點擊>>>
“CDA報名”
了解CDA考試詳情;
? 想學習CDA考試教材,點擊>>> “CDA教材” 了解CDA考試詳情;
? 想加入CDA考試題庫,點擊>>> “CDA題庫” 了解CDA考試詳情;
? 想了解CDA考試含金量,點擊>>> “CDA含金量” 了解CDA考試詳情;