Nạp và hợp nhất 2 dữ liệu PISA
#Nạp 2 dữ liệu
students = read.csv('C:/Users/Dell/Desktop/Dataset/PISA VN 2015.csv')
schools = read.csv('C:/Users/Dell/Desktop/Dataset/PISA VN SCHOOLS 2015.csv')
#Merge 2 dữ liệu
pisa = merge(students, schools, by = "CNTSCHID")
#Biến trong dữ liệu khá dài, có thể đổi tên bằng hàm label
#labels(pisa$PV1MATH) = "Math"
#labels(pisa$PV1SCIE) = "Science"
#labels(pisa$PV1READ) = "Reading"
#Summary
summary(pisa)
## CNTSCHID AGE Gender PARED
## Min. :70400001 Min. :15.33 Boys :2786 Min. : 3.000
## 1st Qu.:70400052 1st Qu.:15.50 Girls:3040 1st Qu.: 9.000
## Median :70400096 Median :15.75 Median : 9.000
## Mean :70400097 Mean :15.78 Mean : 9.374
## 3rd Qu.:70400143 3rd Qu.:16.00 3rd Qu.:12.000
## Max. :70400188 Max. :16.25 Max. :17.000
## NA's :14
## HEDRES MISCED FISCED HISCED
## Min. :-4.3706 Min. :0.000 Min. :0.000 Min. :0.00
## 1st Qu.:-1.5169 1st Qu.:1.000 1st Qu.:1.000 1st Qu.:2.00
## Median :-1.1119 Median :2.000 Median :2.000 Median :2.00
## Mean :-1.0470 Mean :2.069 Mean :2.296 Mean :2.58
## 3rd Qu.:-0.7026 3rd Qu.:3.000 3rd Qu.:4.000 3rd Qu.:4.00
## Max. : 1.1767 Max. :6.000 Max. :6.000 Max. :6.00
## NA's :20 NA's :34 NA's :88 NA's :14
## WEALTH ESCS INSTSCIE SCIEEFF
## Min. :-7.635 Min. :-5.657 Min. :-1.9301 Min. :-3.7565
## 1st Qu.:-2.829 1st Qu.:-2.539 1st Qu.: 0.0125 1st Qu.:-0.8585
## Median :-2.163 Median :-1.982 Median : 0.3708 Median :-0.3473
## Mean :-2.219 Mean :-1.822 Mean : 0.4835 Mean :-0.2662
## 3rd Qu.:-1.504 3rd Qu.:-1.221 3rd Qu.: 1.0218 3rd Qu.: 0.3155
## Max. : 3.211 Max. : 1.950 Max. : 1.7359 Max. : 3.2775
## NA's :15 NA's :1 NA's :17 NA's :19
## JOYSCIE ICTRES HOMEPOS HEDRES.1
## Min. :-2.1154 Min. :-3.508 Min. :-8.955 Min. :-4.3706
## 1st Qu.: 0.5094 1st Qu.:-2.587 1st Qu.:-2.669 1st Qu.:-1.5169
## Median : 0.5094 Median :-1.855 Median :-2.047 Median :-1.1119
## Mean : 0.6448 Mean :-1.795 Mean :-2.042 Mean :-1.0470
## 3rd Qu.: 1.1049 3rd Qu.:-1.117 3rd Qu.:-1.354 3rd Qu.:-0.7026
## Max. : 2.1635 Max. : 3.497 Max. : 2.770 Max. : 1.1767
## NA's :19 NA's :34 NA's :2 NA's :20
## CULTPOSS PV1MATH PV1READ PV1SCIE
## Min. :-1.8413 Min. :201.7 Min. :107.1 Min. :292.7
## 1st Qu.:-0.8310 1st Qu.:440.0 1st Qu.:442.5 1st Qu.:470.9
## Median :-0.4113 Median :493.4 Median :489.5 Median :523.9
## Mean :-0.4444 Mean :496.1 Mean :489.9 Mean :524.8
## 3rd Qu.: 0.1157 3rd Qu.:551.5 3rd Qu.:537.6 3rd Qu.:574.8
## Max. : 2.1655 Max. :820.1 Max. :744.1 Max. :807.3
## NA's :52
## STRATUM SCHSIZE CLSIZE STRATIO
## VNM0313:989 Min. : 113 Min. :13.00 Min. : 4.314
## VNM0208:884 1st Qu.: 650 1st Qu.:38.00 1st Qu.:14.024
## VNM0101:806 Median :1090 Median :38.00 Median :16.627
## VNM0207:790 Mean :1082 Mean :40.57 Mean :16.497
## VNM0102:764 3rd Qu.:1419 3rd Qu.:43.00 3rd Qu.:18.983
## VNM0314:679 Max. :4016 Max. :53.00 Max. :38.651
## (Other):914 NA's :34
## SCHLTYPE Region Area
## Min. :1.000 CENTRAL:2006 REMOTE: 410
## 1st Qu.:3.000 NORTH :1958 RURAL :2368
## Median :3.000 SOUTH :1862 URBAN :3048
## Mean :2.849
## 3rd Qu.:3.000
## Max. :3.000
## NA's :35
Một số thử nghiệm với plot_frq trong sjPlot : vẽ Barchart
#Barchart by region, kèm đổi tên tittle
library(sjPlot)
## Install package "strengejacke" from GitHub (`devtools::install_github("strengejacke/strengejacke")`) to load all sj-packages at once!
plot_frq(pisa$Region, title = "Tần số theo vùng miền")#Đây là 1 hàm trong sjPlot(x,..) library dùng để phân tích rồi vẽ biểu đồ về số lượng và tần số của 1 biến số
plot_frq(pisa$Area, axis.title = "Tỉ lệ theo khu vực", axis.labels = c("Vùng xa", "Nông thôn", "Thành thị"))
Phân tích từng thành phần con của biến phân loại
sjp.xtab(pisa$Area, pisa$Region) #sjp.xtab là hàm thuộc sjPlot, ở đây pisa$Area là chính, pisa$region là con, được dùng phân các thành phần trong pisa$Area thành các phần nhỏ hơn
sjp.xtab(pisa$Area, pisa$Region, coord.flip=T)#mặc định sjp.xtab là đặt dọc, nay ta thêm coord.flip = T , True tức sẽ thực hiện flip(sưap) xoay biểu đồ 90 độ -> biểu đồ ngang
#Biểu đồ đẹp hơn, không còn chồng số, chữ cái
2. Task 2
Vẽ biểu đồ Histogram
#using function hist() to create a histogram (Biểu đồ tần số) with R built-in base function
hist(pisa$PV1SCIE, col = "lightblue")
#Một chút sửa đổi, customize
hist(pisa$PV1SCIE, col = "lightblue", border = "white", main ="Phân bố điểm Khoa học", xlab = "Điểm khoa học", ylab = "Số lượng")
#more graphical
hist(pisa$PV1SCIE, col = "lightblue", border = "white", xlab = "Science Score", ylab = "Frequency", main = "Distribution of Science Score", breaks = 20)
hist(pisa$PV1SCIE, col = "lightblue", border = "white", xlab = "Science Score", ylab = "Frequency", main = "Distribution of Science Score", breaks = 20, prob = 1)
Adding line representatives of density
hist(pisa$PV1SCIE, col = "lightblue", border = "white", prob = T)
lines(density(pisa$PV1SCIE), col = "red")
Biểu đồ phân bố histogram cho từng gender nam và nữ được ghép lại với nhau
#Distribution for both sex
p1 = hist(pisa$PV1SCIE[pisa$Gender=="Boys"], plot =F) #plot = F thì trả về sẽ chỉ là các dữ liệu số, không vẽ ra hình liền khi chạy trên workpace, plot = T thì sẽ vẽ hình liền
p2 = hist(pisa$PV1SCIE[pisa$Gender=="Girls"], plot=F)
plot(p1, col="yellow", border="white")
plot(p2,add = T, col=scales::alpha("red", 0.6), border = 'white') # scales::alpha('color', number) là hàm tự chỉnh màu theo ý thích
#Rất khó nhìn do 2 biểu đồ chồng lên nhau, vùng nào chồng thì 2 màu sắc sẽ pha lại, ở đây pha thành màu cam
Task 3 : Biểu đồ phân bố mật độ với nhiều đối tượng, với package lattice
Nếu ở base package, ta có thể vẽ density dạng đường, nhưng chỉ với dữ liệu một biến số liên tục, còn khi muốn so sánh/vẽ nhiều biến số trên một biểu đồ, ta phải dùng packages khác
library(lattice)
densityplot(data = pisa,~PV1SCIE, groups = Gender)#Gender có 2 phân nhóm
densityplot(~PV1SCIE, data = pisa, groups = Area)#Are có 3 phân nhóm
densityplot(data = pisa, ~PV1SCIE, groups = Area, auto.key = list(space = 'right'))
#auto.key là hàm base, chức năng hiển thị plot của x và y, ở đây chỉ có biến x, và x có 3 phân nhóm nên sẽ hiện chú thích 3 nhóm đó
#list là hàm xây dựng, liệt kê
#space = 'ở đây có thể chọn top, bottom, left, right,..' để xác định khoảng không gian chú thích( legend) xuất hiện tương ứng với biểu đồ
table(pisa$Area)
##
## REMOTE RURAL URBAN
## 410 2368 3048
DIsplay various graph in a plot (use gridExtra package)
p1 = densityplot(~PV1SCIE, groups = Area, data = pisa)#densityplot là hàm trong lattice library
p2 = densityplot(~PV1MATH, groups = Area, data = pisa)
p3 = densityplot(~PV1READ, groups = Area, data = pisa)
library(gridExtra)
grid.arrange(p1, p2, p3, ncol=3, bottom = "Các biểu đồ điểm khoa học, toán và đọc")#Xếp theo cột
grid.arrange(p1, p2, p3, nrow = 3)#Xếp theo hàng
#Biểu đồ box bằng thư viện sjPlot với hàm sjp.grapfrq(,type ='box')
sjp.grpfrq(pisa$PV1SCIE, pisa$Region, type = "box")#sjp.grapfrq bắt buộc phải có 2 đối số (argument)
## Warning in rq.fit.br(wx, wy, tau = tau, ...): Solution may be nonunique
## Warning in rq.fit.br(wx, wy, tau = tau, ...): Solution may be nonunique
## Warning in rq.fit.br(wx, wy, tau = tau, ...): Solution may be nonunique
Task 4: Thử với hàm boxplot mặc định
par(mfrow=c(1, 3))#chia màn hình thành 3 cửa sổ ( 1 dòng, 3 cột )
boxplot(pisa$PV1SCIE, col="purple")
boxplot(pisa$PV1SCIE ~ pisa$Gender, col=c("blue", "red"))
boxplot(pisa$PV1SCIE ~ pisa$Region, col=c("blue", "red", "yellow"))
Task 5: Scatter plot ( biểu đồ tương quan )
plot(pisa$PV1SCIE ~ pisa$PARED, pch = 16, col="blue", xlab = "PARED", ylab = "Điểm khoa học", main = 'Mỗi liên quan giữa Pared và điểm khoa học')
#Hàm plot mặc định, dùng vẽ scatter plot, xlab là tiêu đề trục hoành, ylab là tiêu đề trục tung, main là tiêu đề biểu đồ
abline(lm(pisa$PV1SCIE ~ pisa$PARED), col="red", lwd = 2)
#Hàm vẽ hồi quy tuyến tính mặc định, nhưng không nhiều thông tin và đẹp
#lwd là số chỉ độ dày của đường tuyến tính
#Dùng boxplot trong sjPlot
library(sjPlot)
sjp.grpfrq(pisa$PV1SCIE, pisa$PARED, type="box")
## Warning in rq.fit.br(wx, wy, tau = tau, ...): Solution may be nonunique
Hai cách thể hiện biểu đồ khác nhau trên cùng đối tượng, biểu đồ nào trực quan hơn.
Task 6 Biểu đồ Likert
big5 = read.csv('C:/Users/Dell/Desktop/Dataset/Big Five Personality Data.csv')
dim(big5)
## [1] 19719 57
head(big5)
## race age engnat gender hand source country E1 E2 E3 E4 E5 E6 E7 E8 E9
## 1 3 53 1 1 1 1 US 4 2 5 2 5 1 4 3 5
## 2 13 46 1 2 1 1 US 2 2 3 3 3 3 1 5 1
## 3 1 14 2 2 1 1 PK 5 1 1 4 5 1 1 5 5
## 4 3 19 2 2 1 1 RO 2 5 2 4 3 4 3 4 4
## 5 11 25 2 2 1 2 US 3 1 3 3 3 1 3 1 3
## 6 13 31 1 2 1 2 US 1 5 2 4 1 3 2 4 1
## E10 N1 N2 N3 N4 N5 N6 N7 N8 N9 N10 A1 A2 A3 A4 A5 A6 A7 A8 A9 A10 C1 C2
## 1 1 1 5 2 5 1 1 1 1 1 1 1 5 1 5 2 3 1 5 4 5 4 1
## 2 5 2 3 4 2 3 4 3 2 2 4 1 3 3 4 4 4 2 3 4 3 4 1
## 3 1 5 1 5 5 5 5 5 5 5 5 5 1 5 5 1 5 1 5 5 5 4 1
## 4 5 5 4 4 2 4 5 5 5 4 5 2 5 4 4 3 5 3 4 4 3 3 3
## 5 5 3 3 3 4 3 3 3 3 3 4 5 5 3 5 1 5 1 5 5 5 3 1
## 6 5 1 5 4 5 1 4 4 1 5 2 2 2 3 4 3 4 3 5 5 3 2 5
## C3 C4 C5 C6 C7 C8 C9 C10 O1 O2 O3 O4 O5 O6 O7 O8 O9 O10
## 1 5 1 5 1 4 1 4 5 4 1 3 1 5 1 4 2 5 5
## 2 3 2 3 1 5 1 4 4 3 3 3 3 2 3 3 1 3 2
## 3 5 1 5 1 5 1 5 5 4 5 5 1 5 1 5 5 5 5
## 4 4 5 1 4 5 4 2 3 4 3 5 2 4 2 5 2 5 5
## 5 5 3 3 1 1 3 3 3 3 1 1 1 3 1 3 1 5 3
## 6 4 3 3 4 5 3 5 3 4 2 1 3 3 5 5 4 5 3
#Ta thấy các biến E1, E2…E10, N1…10 dữ liệu là các con số (numreic)
test = big5[, c("gender", "E1", "E2", "E3", "E4", "E5")]
test$E1 = as.factor(test$E1) #Chuyển numeric sang character, từ đó có thể đếm số lượng 'số 1,2..'
test$E2 = as.factor(test$E2)
test$E3 = as.factor(test$E3)
test$E4 = as.factor(test$E4)
test$E5 = as.factor(test$E5)
library(sjPlot) #Gọi thư viện sjPlot
plot_likert(test) #sjp.likert(test) là code cũ nên không đúng
## Warning: Detected uneven category count in items. Dropping last category.
## Warning in freq[valid] <- counts: number of items to replace is not a
## multiple of replacement length
## Warning in freq[valid] <- counts: number of items to replace is not a
## multiple of replacement length
## Warning in freq[valid] <- counts: number of items to replace is not a
## multiple of replacement length
## Warning in freq[valid] <- counts: number of items to replace is not a
## multiple of replacement length
## Warning in freq[valid] <- counts: number of items to replace is not a
## multiple of replacement length
## Warning in freq[valid] <- counts: number of items to replace is not a
## multiple of replacement length
Task 7: Biểu đồ tương quan
ob = read.csv('C:/Users/Dell/Desktop/Dataset/Obesity data.csv')
#Tạo ra biến mới gọi là "OB" dựa vào biến bmi: nếu bmi < 18.5 thì OB = "Underweight"; bmi từ 18.5 đến 24.9 thì OB="Normal"; bmi từ 25.0 đến 29.9 thì OB="Overweight"; bmi từ 30.0 trở lên, OB="Obese"
ob$OB [ob$bmi < 18.5] = "Underweight"
ob$OB [ob$bmi >= 18.5 & ob$bmi < 24.9] = "Normal"
ob$OB [ob$bmi >= 25.0 & ob$bmi < 29.9] = "Overweight"
ob$OB [ob$bmi >= 30] = "Obese"
#Nếu bên công nghệ thông tin thay vì tốn công tận 4 dòng như trên ta dùng hàm ifelse - là hàm base
#ob$OB = ifelse(ob$bmi < 18.5, 'Underweight',ifelse(ob$bmi >= 18.5 & ob$bmi < 24.9,"Normal",ifelse(ob$bmi >= 25.0 & ob$bmi < 29.9, "Overweight", "Obese")))
ob$OB = factor(ob$OB, levels=c("Underweight", "Normal", "Overweight", "Obese"))
#Tìm hiểu phân bố của OB
library(ggplot2)
p = ggplot(data=ob, aes(OB, fill=OB)) + geom_bar()
p = p + xlab("Obesity group") + ylab("Frequency")
p = p + ggtitle("Số lượng của từng nhóm cân nặng")
p + theme(legend.position = "right") #legend.position = 'top, bottom, right, left, none'
Task 8: Vẽ biểu đồ tương quan giữa weight và pcfat dùng ggplot2
#Biểu đồ đơn giản
p = ggplot(data=ob, aes(x=weight, y=pcfat))
p = p +geom_point() +geom_smooth()
p
## `geom_smooth()` using method = 'gam' and formula 'y ~ s(x, bs = "cs")'
Ta thấy chưa đẹp lắm, nên chỉnh lại chút về các trục, tên biểu đồ
p = p + xlab("Weight") + ylab("Percent body fat") + ggtitle("Weight and Percent Body Fat")
p = p + theme(plot.title=element_text(hjust=0.5))
p
## `geom_smooth()` using method = 'gam' and formula 'y ~ s(x, bs = "cs")'
Biểu đồ trên gộp cả nam và nữ ( tức che dấu ), biết đâu giữa nam và nữ lại có khác biệt
#Tách theo từng giới: nam và nữ
p = ggplot(data=ob, aes(x=weight, y=pcfat, fill=gender, col=gender))
p = p + geom_point() + geom_smooth()
p
## `geom_smooth()` using method = 'loess' and formula 'y ~ x'
Đôi lúc, ta thích một themes nào đó ( ví dụ themes/chủ đề của tờ new york time, washington post, economist,..) có một package giúp ta thực hiện mong muốn
library(ggthemes)
p + theme_economist()
## `geom_smooth()` using method = 'loess' and formula 'y ~ x'
#Vẽ theo style Economist
#Vẽ theo các theme khác
p + theme_wsj()
## `geom_smooth()` using method = 'loess' and formula 'y ~ x'
p + theme_tufte()
## `geom_smooth()` using method = 'loess' and formula 'y ~ x'
p + theme_clean()
## `geom_smooth()` using method = 'loess' and formula 'y ~ x'
p + theme_hc()
## `geom_smooth()` using method = 'loess' and formula 'y ~ x'
Tương quan đa chiều
head(ob)
## id gender height weight bmi age bmc bmd fat lean pcfat OB
## 1 1 F 150 49 21.8 53 1312 0.88 17802 28600 37.3 Normal
## 2 2 M 165 52 19.1 65 1309 0.84 8381 40229 16.8 Normal
## 3 3 F 157 57 23.1 64 1230 0.84 19221 36057 34.0 Normal
## 4 4 F 156 53 21.8 56 1171 0.80 17472 33094 33.8 Normal
## 5 5 M 160 51 19.9 54 1681 0.98 7336 40621 14.8 Normal
## 6 6 F 153 47 20.1 52 1358 0.91 14904 30068 32.2 Normal
vars = ob[,c("gender", "age", "weight", "bmi", "pcfat")]
library(GGally)
## Registered S3 method overwritten by 'GGally':
## method from
## +.gg ggplot2
ggpairs(data=vars, mapping=aes(color=gender))
## `stat_bin()` using `bins = 30`. Pick better value with `binwidth`.
## `stat_bin()` using `bins = 30`. Pick better value with `binwidth`.
## `stat_bin()` using `bins = 30`. Pick better value with `binwidth`.
## `stat_bin()` using `bins = 30`. Pick better value with `binwidth`.
#Biểu đồ tương quan + biểu đồ phân bố dùng package ggExtra
p = ggplot(data=ob, aes(x=weight, y=pcfat, fill=gender, col=gender))
p = p + geom_point() + geom_smooth()
library(ggExtra)
p = ggMarginal(p, type="density", groupColour=T, groupFill=T)
## `geom_smooth()` using method = 'loess' and formula 'y ~ x'
## `geom_smooth()` using method = 'loess' and formula 'y ~ x'
p
students = read.csv("C:/Users/Dell/Desktop/Dataset/PISA VN 2015.csv")
schools = read.csv("C:/Users/Dell/Desktop/Dataset/PISA VN SCHOOLS 2015.csv")
pisa = merge(students,schools, by="CNTSCHID")
head(pisa,3)
## CNTSCHID AGE Gender PARED HEDRES MISCED FISCED HISCED WEALTH ESCS
## 1 70400001 15.58 Boys 9 -1.0418 1 2 2 -2.0697 -1.7899
## 2 70400001 15.92 Boys 12 -2.3041 1 4 4 -1.7903 -1.5423
## 3 70400001 15.42 Girls 9 -0.7218 1 2 2 -2.1942 -2.0475
## INSTSCIE SCIEEFF JOYSCIE ICTRES HOMEPOS HEDRES.1 CULTPOSS PV1MATH
## 1 0.9798 0.1421 2.1635 -1.5244 -2.0537 -1.0418 -0.7273 439.923
## 2 1.7359 -0.8432 2.1635 -1.9305 -2.2627 -2.3041 -0.2031 406.251
## 3 -0.2063 -0.1824 -0.1808 -1.6093 -1.9675 -0.7218 -0.2220 414.369
## PV1READ PV1SCIE STRATUM SCHSIZE CLSIZE STRATIO SCHLTYPE Region Area
## 1 412.290 475.612 VNM0313 883 18 22.075 3 SOUTH URBAN
## 2 409.598 450.320 VNM0313 883 18 22.075 3 SOUTH URBAN
## 3 384.307 405.787 VNM0313 883 18 22.075 3 SOUTH URBAN
p= ggplot(data=pisa, aes(x=Region, y=PV1SCIE, fill=Region))
p= p+geom_boxplot()
p
#Điểm có phụ thuộc thành phần kinh tế, trình độ học vấn cha mẹ
p= ggplot(data=pisa, aes(x=factor(PARED), y=PV1SCIE, fill=factor(PARED)))
p = p + geom_boxplot() + geom_jitter(alpha=0.05)
p
#WEALTH có ảnh hưởng?
p= ggplot(data=pisa, aes(x=WEALTH, y=PV1SCIE, fill=Region))
p = p + geom_point() + geom_smooth()
p
## `geom_smooth()` using method = 'gam' and formula 'y ~ s(x, bs = "cs")'
## Warning: Removed 15 rows containing non-finite values (stat_smooth).
## Warning: Removed 15 rows containing missing values (geom_point).
p= ggplot(data=pisa, aes(x=WEALTH, y=PV1SCIE, col=Area, fill=Area))
p = p + geom_point() + geom_smooth()
p
## `geom_smooth()` using method = 'gam' and formula 'y ~ s(x, bs = "cs")'
## Warning: Removed 15 rows containing non-finite values (stat_smooth).
## Warning: Removed 15 rows containing missing values (geom_point).