#Phần I. Lập trình R căn bản
#Bài 1
#1. Vectơ (1, 2, 3, ..., 19, 20)
vec1 <- seq(1, 20)
vec1
## [1] 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
#2 Vectơ (20, 19, ..., 2, 1)
vec2 <- seq(20, 1)
vec2
## [1] 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1
#3 Vectơ (1, 2, 3, ..., 19, 20, 19, 18, ..., 2, 1)
vec3 <- c(seq(1, 20), seq(19, 2))
vec3
## [1] 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 19 18 17 16 15
## [26] 14 13 12 11 10 9 8 7 6 5 4 3 2
#4
#Để tạo ra véc tơ e, có thể sử dụng hàm rep() của R để lặp lại tmp trong e:
tmp <- c(4, 6, 3)
e <- rep(tmp, times = 10)
e
## [1] 4 6 3 4 6 3 4 6 3 4 6 3 4 6 3 4 6 3 4 6 3 4 6 3 4 6 3 4 6 3
#Để tạo ra véc tơ f, có thể sử dụng hàm rep() kết hợp với c() để thêm số 4 vào cuối véc tơ e:
f <- c(e, 4)
f
## [1] 4 6 3 4 6 3 4 6 3 4 6 3 4 6 3 4 6 3 4 6 3 4 6 3 4 6 3 4 6 3 4
#Bài 2
set.seed(50)
xVec <- sample(0:999, 250, replace = T)
yVec <- sample(0:999, 250, replace = T)
#(a)
vector_a = yVec[-1] - xVec[-length(xVec)]
vector_a
## [1] -359 692 -724 40 -626 -719 -809 527 -89 -829 248 144 -749 -352 -220
## [16] -249 387 -492 85 -106 303 -97 -436 146 282 -206 -385 -96 -567 -757
## [31] 287 277 -562 292 -89 -93 -847 -822 -203 679 309 -199 -273 4 -47
## [46] 142 122 414 -602 -304 -674 -8 -662 -168 -349 -63 -221 115 1 -600
## [61] -382 -487 2 375 19 -113 -634 107 60 47 214 -325 -49 -290 169
## [76] 290 -624 457 -408 581 -189 204 -80 409 209 -410 461 37 -127 185
## [91] 382 -446 44 -56 -270 -598 -378 -155 134 -187 109 316 -139 158 305
## [106] -39 -119 182 441 -403 -107 615 614 -378 -464 31 -385 665 674 -217
## [121] -279 -406 -45 -489 -350 -451 -18 660 504 -6 60 -130 -379 -302 -219
## [136] -21 438 129 -201 -275 131 694 -96 -176 117 -113 887 -439 -126 -148
## [151] 392 -158 444 -291 232 -12 -274 477 -510 336 -759 -363 -195 -220 160
## [166] -308 -333 302 -183 227 -12 428 665 -301 -8 222 -50 -444 -425 -650
## [181] -424 318 154 238 -727 71 472 908 265 654 -644 -754 657 -382 -313
## [196] 910 -381 394 -596 602 397 -572 378 -274 -271 601 -791 -378 -461 39
## [211] 163 -118 -332 -170 -94 262 -474 566 -273 -366 -400 374 42 100 135
## [226] 609 -527 580 -219 128 -524 620 -206 410 -280 -66 -50 252 279 48
## [241] -595 -59 -623 247 514 62 -102 475 287
#(b)
vector_b = sin(yVec[-1])/cos(xVec[-length(xVec)])
vector_b
## [1] -1.17240581 1.17912119 -1.18405690 0.91383388 -1.03466431
## [6] -4.54995011 0.96744602 -0.60165877 -1.45069126 4.77314012
## [11] -0.87493498 2.55269394 -1.09592154 0.52599111 -0.58209835
## [16] 1.00173656 -0.30068981 -1.24434675 -0.87814679 -0.01297143
## [21] 0.74708907 -0.70304510 -20.16375764 1.01149224 -2.44831431
## [26] 8.21654493 -0.18713516 -1.28175667 -1.04007889 2.32511346
## [31] 0.30936979 -0.03142845 0.13852990 1.12311909 -0.35660630
## [36] 1.05612441 0.61851802 0.99257387 -1.24624168 -3.27973512
## [41] 0.73776169 0.53909056 0.59126157 -0.24567710 -2.51185638
## [46] -5.77079655 1.07157635 -1.08948381 0.99057131 -0.75603199
## [51] -0.66765815 -1.18413772 -2.04581314 0.58751132 -3.44748597
## [56] -0.83156650 0.79089273 1.21448060 -0.87285882 -2.08273830
## [61] 0.59939389 0.00000000 0.46058752 -0.93104100 -1.33148856
## [66] -0.08985446 1.90152477 9.03582187 0.23197843 0.75447547
## [71] -1.72102029 1.30261307 1.26111791 -0.52918358 -0.80400191
## [76] 3.61432300 -1.28257757 -1.01957014 -0.14326352 -0.13984157
## [81] 0.93489723 44.45266049 0.84879241 1.03599894 1.06215150
## [86] -0.99538657 -0.92525910 -1.85905156 -1.13523700 2.26022833
## [91] -1.39414741 -1.08726749 1.28458050 -14.27631579 0.35215314
## [96] -0.96324077 -2.12823293 0.62640479 3.85631482 -2.38983690
## [101] 2.49092447 -0.24709327 -0.40883224 13.23192970 1.30040049
## [106] -1.13666480 1.93685969 0.36331935 1.65634429 -2.27093778
## [111] 7.43403244 -7.83206398 -1.02923436 -1.49722581 1.85128150
## [116] 0.29847442 -0.89926413 0.47955111 1.54938327 73.38987154
## [121] -4.15756270 -23.34750989 -0.18523880 1.13142145 0.30891204
## [126] 1.31397148 1.36891757 -0.81562375 1.19542291 3.52600513
## [131] 7.07508558 0.76396099 -11.56612997 -2.26901456 0.28463076
## [136] -1.28088838 -1.15650611 -1.66374145 0.17724777 1.11947959
## [141] -0.94299568 0.86166639 -0.25703697 -1.68635919 -1.83967514
## [146] 0.33970529 0.18618231 0.48191908 0.49269232 -213.74554174
## [151] -0.85073887 -3.43286395 -1.77467428 -1.56762066 -0.76146774
## [156] 2.67368530 0.09646823 5.78220626 0.05725002 -0.63768319
## [161] 0.34047746 -0.73599637 0.58628813 -44.97227747 17.14918285
## [166] -9.83279992 -0.33073449 16.34713189 0.45723708 0.41501918
## [171] 0.89164296 0.63114475 -0.61879787 1.10698992 -2.11758798
## [176] 0.71053046 0.65835495 1.54289030 0.07877718 0.00000000
## [181] 0.73547993 -0.78049129 0.45497512 -3.49933520 0.85415348
## [186] 0.43002471 3.49991856 0.05346361 0.20966456 2.92825394
## [191] 1.59249748 0.09785974 1.87023492 1.59486678 -0.69404053
## [196] -1.16521258 4.67695014 -3.57474788 1.99444312 -0.84927490
## [201] 1.33276064 -0.59765860 0.18336188 0.26188648 -0.87979353
## [206] -0.76044135 0.78305929 -0.07755715 -1.27397613 0.70532666
## [211] -0.47127381 1.41535669 0.55206430 -0.48032852 1.03152656
## [216] -1.17042534 -1.81759372 0.97200315 -1.65764774 -1.00250214
## [221] 0.35934231 -0.81613658 -1.05241135 0.31508672 -0.40536967
## [226] -1.36393769 1.10638927 0.66811992 0.58843372 0.81980761
## [231] 0.09380321 0.04082033 0.90521120 1.01526009 -11.85003825
## [236] -1.31166711 2.70642672 0.52562918 -4.71623127 -0.71718964
## [241] 1.50574675 -0.81741731 -1.72650328 0.83179237 -1.02614926
## [246] -1.74828942 -1.19748013 -1.03957071 -1.32464191
#(c)
n = length(xVec)
vector_c = xVec[-c(n,(n-1))] + 2*xVec[c(1,n)] - xVec[-c(1,2)]
vector_c
## [1] 282 1506 691 803 783 2097 841 1061 1169 2476 19 843 1444 1880 671
## [16] 1303 243 1912 1144 1548 188 1276 1076 1397 885 1801 639 1410 1143 2535
## [31] 284 1386 1182 992 -31 1499 1298 2245 578 988 659 1607 1241 2100 142
## [46] 1460 639 1049 572 2406 694 1511 916 1193 778 2187 1434 652 143 2100
## [61] 1103 1612 607 1097 377 2113 990 1303 898 1534 154 1868 1555 1875 23
## [76] 1566 729 1725 789 1639 621 1412 1477 1242 418 1839 918 1854 948 996
## [91] 663 1399 408 1774 195 1448 1328 1636 649 1829 613 1882 660 1479 600
## [106] 1325 1312 1554 564 1983 864 1203 130 1667 1122 2023 1005 1332 436 990
## [121] 769 1723 451 1558 1036 2437 1023 925 576 1949 442 1158 576 2094 962
## [136] 1197 989 1565 860 2204 289 1358 1316 951 670 1644 459 2141 498 1373
## [151] 822 1374 993 1882 199 1706 944 1352 532 1278 861 1744 887 1392 271
## [166] 2341 918 1771 876 1420 1045 1404 312 1207 1222 1475 344 1825 657 1800
## [181] 1227 1758 42 1063 1220 2364 796 1397 445 812 1152 1878 21 2220 932
## [196] 1566 898 1541 1105 868 343 2073 460 1867 787 725 611 1642 939 2119
## [211] 970 1629 981 1850 297 1499 844 858 885 2102 370 1172 1469 2267 247
## [226] 1620 317 1707 1014 1547 1120 1379 528 1667 417 1368 894 1480 460 1175
## [241] 1001 2256 972 1453 383 1777 1395 1006
# (d)
vector_d = sum(exp(-xVec[-1])/xVec[-n]+10)
vector_d
## [1] 2490
#bài 3
#chúng ta có thể sử dụng tính chất của hàm cumprod và hàm seq trong R để tính giá trị của biểu thức đã cho.
#Đầu tiên, ta tạo ra một vector chứa các giá trị từ 2 đến 39 như sau:
x <- seq(2, 39)
#Tiếp theo, ta tạo ra một vector chứa các phân số tương ứng với mỗi phần tử trong vector đó:
fractions <- x / seq(3, 40)
#Sau đó, ta sử dụng hàm cumprod để tính tích phân trên từng phần tử của vector fractions:
y <- cumprod(fractions)
#Cuối cùng, ta thêm 1 và giá trị đầu tiên của vector y và tính tổng của các phần tử trong vector đó:
result <- sum(c(1, y))
result
## [1] 6.557086
#Phần 2 Lập trình hàm trong R #bài 1
myvector <- c(1, 2, 3, 4, 5,6)
#1 .Hàm tính tổng, giá trị trung bình các phần tử của myvector
tong = function(x){
sum = 0
for(i in 1:length(x)) {
sum = sum + x[i]
}
return(sum)
}
trung_binh = function(x){
mean = tong(x)/length(x)
return(mean)
}
#2 Hàm tính giá trị nhỏ nhất và lớn nhất của myvector:
MIN =function(x){
min = x[1]
for(i in 1:length(x)){
if(min > x[i]){
min = x[i]
}
}
return(min)
}
MAX = function(x){
max = x[1]
for(i in 1:length(x)){
if(max < x[i]){
max = x[i]
}
}
return(max)
}
#3 Hàm tính giá trị phương sai và độ lệch chuẩn của myvector:
phuong_sai = function(x){
a = (x - trung_binh(x))^2
sum = 0
for (i in 1:length(x)) {
sum = sum + a[i]
}
return(sum/(length(x)-1))
}
tong(x)
## [1] 779
trung_binh(x)
## [1] 20.5
MIN(x)
## [1] 2
MAX(x)
## [1] 39
phuong_sai(x)
## [1] 123.5
#Phần 3 Tính hiệp phương sai #Bài1
#Viết hàm tính hiệp phương sai:
#Viết hàm tính hiệp phương sai:
covariance = function(x,y){
a = (x-mean(x))*(y-mean(y))
sum = 0
if(length(x)==length(y)){
for(i in 1:length(x)){
sum = sum + a[i]
}
}
return(sum/(length(x)-1))
}
x = c(1,2,3,7,4,6,9,-5)
y = c(2,3,6,7,1,-6,6,2)
covariance(x,y)
## [1] 2.303571
# Tạo dãy các phân số cần tính
frac <- as.numeric(sprintf("2/3%s", paste0(sprintf("%d/%d", seq(4, 39, by = 2), seq(5, 39, by = 2)), collapse = "+")))
## Warning: NAs introduced by coercion
# Tính tổng của dãy phân số
result <- sum(c(1, frac))
# In kết quả
result
## [1] NA
#Phần 4 Trực quan dữ liệu Trực quan hóa dữ liệu Visualization in R Sự cần thiết của trực quan dữ liệu Một số khái niệm về trực quan Có một vấn đề được đặt ra là: Với hàng triệu mẫu DNA và con số ngày nay cùng với hàng triệu ca nhiễm COVID-19 trên toàn thế giới ngày càng gia tăng thì chúng ta cần làm gì để có thể biết được xu hướng, ý nghĩa và cách phân phối của dữ liệu (ứng với từng quốc gia cho các ca nhiễm COVID-19 chẳng hạn). Việc phân tích mối tương quan hoặc xu hướng phân bố của dữ liệu đóng vai trò cực kỳ quan trọng trong nghiên cứu khoa học và đánh giá thống kê.
Người Trung Hoa hay có câu một hình ảnh có giá trị tương đương với một vạn chữ. Quả đúng như vậy, với một “đại dương” số liệu thì việc khai thác hiệu quả “đại dương” này là một vấn đề nan giải. Chúng ta cần phải hiểu rằng, khi có dữ liệu thì việc truyền tải thông tin tới người khác là vô cùng khó khăn. Phải làm thế nào để họ hiểu, họ nắm được xem bộ dữ liệu đó nói về cái gì, miêu tả cái gì và rút ra điều gì từ bộ dữ liệu đó. Chữ viết hoàn toàn có thể sử dụng cho những bộ dữ liệu đơn giản nhưng không thể thực hiện được việc truyền tải nội dung về xu hướng và dao dộng của dữ liệu
Một số biểu đồ trực quan
Hiển thị dữ liệu, mô phỏng dữ liệu hay trực quan dữ liệu (Visualization) nói chung là một bước quan trọng trong tổng thể phân tích dữ liệu. Trước khi phân tích bất kỳ một mô hình nào, việc đầu tiên là chúng ta cần “cảm thụ” được bộ dữ liệu đó, tức là có một cái nhìn khái quát nhất về bộ dữ liệu mà chúng ta đang có. Hiện nay, trong phân tích nghiên cứu khoa học, một số biểu đồ thường được sử dụng, đó là:
1.Biểu đồ tương quan (scatterplot) 2.Biểu đồ phân phối (histogram) 3.Biểu đồ thanh (barchat) 4.Biểu đồ hộp (box plot) Lịch sử hiển thị dữ liệu Biểu đồ có một lịch sử rất thú vị. Trước thể kỷ 18, dữ liệu khoa học thường được trình bày dạng bảng (tables) và đôi khi biểu đồ được coi là vô dụng vì không phản ánh bất kỳ điều gì. Quan điểm này khá là sai lầm, năm 1786, William Playfair (một nhà kinh tế chính trị học) sáng tạo ra biểu đồ tròn (pie chart), biểu đồ thanh (bar chart) và biểu đồ dây (line chart), những cái mà chúng ta vẫn sử dụng cho tới ngày nay. Mãi đến năm 1832, nhà thiên văn học người Anh là Alexander S. Herche sáng chế ra biểu đồ tương quan (scatter plot) và trở thành rất phổ biến trong khoa học thực nghiệm.
Nguyên tắc thiết kế biểu đồ Hãy làm quen với Edward Tufte, vì ông là một guru - bậc thầy về biểu đồ. Ông là giáo sư thống kê học của Đại học Yale, giáo sư chính trị học và giáo sư về khoa học máy tính của đại học Yale, ông là người có ảnh hưởng rất lớn tới lĩnh vực trực quan dữ liệu. Ông là người đã dám thế chấp căn nhà của mình để vay tiền ngân hàng nghiên cứu và cho ra công trình data visualization mà sau này ông không bao giờ phải hối hận. Tờ báo New York Times gọi ông là Leonardo Da Vinci of Data Edward Tufte đặt ra 4 triết lý và nguyên tắc chính trong trình bày dữ liệu bằng biểu đồ. Có thể tóm gọn như sau “Graphical excellence is that which gives to the viewer the greatest number of ideas in the shortest time with the least ink in the smallest space”. Như vậy, khi trình bày dữ liệu bằng biểu đồ phải để ý tới thông tin của 4 khía cạnh: Lượng thông tin, thời gian, lượng mực in và không gian. Từ đó có thể hiểu 4 nguyên tắc chính khi trình bày dữ liệu chính là: Phản ảnh dữ liệu một cách đầy đủ, tối ưu hóa dữ liệu trên mực in, tối ưu hóa mật độ dữ liệu và trình bày dữ liệu chứ không phải trang trí biểu đồ.
Thư viện GGPLOT2 Giới thiệu về ggplot2 Chương trình ggplot2 do tác giả Hadley Wickham phát triển và phổ biến là một thư viện rất có ích cho việc biên soạn biểu đồ với chất lượng cao. Cú pháp của ggplot2 được mô phỏng theo việc chồng lấp các lớp (layers); mỗi lớp sẽ có một chức năng riêng. Tuy nhiên có 3 layers chính, đó là:
Lớp xác định biến số cần trực quan dữ liệu Lớp hình thức thể hiện Lớp trang trí, gán nhãn cho biểu đồ..
Lớp biến số Về định nghĩa biến số, thông thường một biểu đồ thường có 2 biến số chính là x và y . Nếu chúng ta muốn thể hiện mối liên quan giữa giới tính và thu nhập thì thông thường x sẽ là biến giới tính và y là biến thu nhập. Ví dụ dưới đây chỉ ra mối liên hệ giữa thu nhập và tuổi thọ trung bình giữa các quốc gia trong thư viện ggplot2.
Cú pháp của lớp này như sau: p=ggplot(data=gapminder,aes(x=gdpPercap,y=lifeExp))
library(ggplot2)
library(gapminder)
p=ggplot(data=gapminder,aes(x=gdpPercap,y=lifeExp))
p + geom_point(aes(color = continent))
Hình thức thể hiện: Hình thức thể hiện của biến x và y thể hiện qua argument có tên là geom(), trong đó có một số loại phổ biến sau:
geom_point(): Biểu đồ tương quan geom_box(): Biểu đồ hộp geom_histogram(): Biểu đồ phân bố geom_line(): Biểu đồ dây geom_text(): Biểu đồ chữ viết geom_smooth(): Chọn đường biểu diễn làm mịn dữ liệu geom_jitter(): Tạo sàng rung, hiển thị dữ liệu, fix lỗi overplotting geom_hline(): Đường biểu diễn nằm ngang geom_vline(): Đường biểu diễn thẳng đứng Trang trí biểu đồ Tiêu đề của biểu đồ
ggtitle(“tên biểu đồ”) + theme(plot.title = element_text(line.height = 0.8, face = “bold”, hjust = 0.5))
Nhãn và trục tung, trục hoành
labs(x=“Tiêu đề trục x”, y = “Tiêu đề trục y”)
Màu và kích thước của nhãn trục tung và hoành
theme(axis.title.x = element_text(color = “blue, size = 14, face =”bold“), axis.title.y = element_text(color =”blue, size = 14, face =“bold”))
Khoảng cách giá trị của trục tung và trục hoành
scale_x_continuous(name=“…”, limits =c(min, max)) + scale_y_continuous(name=“…”, limits = c(min,max)) Một trong những lợi thế của ggplot2 là cho phép người sử dụng hoán chuyển dữ liệu ngày trong phần arguments của hàm ggplot. Chúng ta có thể hoán chuyển đơn vị của trục tung (thu nhập) sang đơn vị log:
library(ggplot2)
library(gapminder)
p1 = ggplot(data=gapminder,aes(x=gdpPercap,y=lifeExp)) + geom_point(aes(color = continent))
p1 <- p1 + scale_x_log10() + geom_smooth(method="loess")
p1
## `geom_smooth()` using formula = 'y ~ x'
geom_smooth() using formula ‘y ~ x’Thực hành ggplot2 Để áp dụng cách sử dụng thư viện ggplot2, chúng ta sử dụng bộ dữ liệu có tên là gapminder, vẽ biểu đồ tương quan giữa 2 biến là tuổi thọ trung bình và thu nhập bình quân. Xem qua về dữ liệu
mydata <- gapminder
head(gapminder)
## # A tibble: 6 × 6
## country continent year lifeExp pop gdpPercap
## <fct> <fct> <int> <dbl> <int> <dbl>
## 1 Afghanistan Asia 1952 28.8 8425333 779.
## 2 Afghanistan Asia 1957 30.3 9240934 821.
## 3 Afghanistan Asia 1962 32.0 10267083 853.
## 4 Afghanistan Asia 1967 34.0 11537966 836.
## 5 Afghanistan Asia 1972 36.1 13079460 740.
## 6 Afghanistan Asia 1977 38.4 14880372 786.
str(gapminder)
## tibble [1,704 × 6] (S3: tbl_df/tbl/data.frame)
## $ country : Factor w/ 142 levels "Afghanistan",..: 1 1 1 1 1 1 1 1 1 1 ...
## $ continent: Factor w/ 5 levels "Africa","Americas",..: 3 3 3 3 3 3 3 3 3 3 ...
## $ year : int [1:1704] 1952 1957 1962 1967 1972 1977 1982 1987 1992 1997 ...
## $ lifeExp : num [1:1704] 28.8 30.3 32 34 36.1 ...
## $ pop : int [1:1704] 8425333 9240934 10267083 11537966 13079460 14880372 12881816 13867957 16317921 22227415 ...
## $ gdpPercap: num [1:1704] 779 821 853 836 740 ...
Chúng ta bắt đầu trực quan dữ liệu
p2 <- ggplot(data = mydata, mapping = aes(x = gdpPercap, y = lifeExp)) p2 + geom_point() -> p2
Thêm một đường biểu diễn tương quan tuyến tính
p2 + geom_smooth(method = “loess”) -> p2
Tuy nhiên, quá nhiều điểm dữ liệu cùng màu, rất khó phân biệt, trực quan theo biến lục địa
ggplot(data = mydata, mapping = aes(x = gdpPercap, y = lifeExp)) + geom_point(aes(color = continent)) +
geom_smooth(method = "loess")
## `geom_smooth()` using formula = 'y ~ x'
Chuyển sang đơn vị log() cho dễ nhìn
ggplot(data = mydata, mapping = aes(x = gdpPercap, y = lifeExp)) + geom_point(aes(color = continent)) +
geom_smooth(method = "loess") +
scale_x_log10()
## `geom_smooth()` using formula = 'y ~ x'
geom_smooth() using formula ‘y ~ x’Gán thêm các nhãn cho biểu đồ
ggplot(data = mydata, mapping = aes(x = gdpPercap, y = lifeExp)) + geom_point(aes(color = continent)) +
geom_smooth(method = "loess") +
scale_x_log10() +
labs(x =" Log GDP per Capita", y = "Life Expectancy") +
ggtitle("Association between GDP Per Capita and Life Expectancy") + theme(plot.title = element_text(lineheight = 0.8, face = "bold", hjust = 0.5))
## `geom_smooth()` using formula = 'y ~ x'
Thay đổi theo phong cách màu của tạp chí “The Economist” như sau:
library(ggthemes)
ggplot(data = mydata, mapping = aes(x = gdpPercap, y = lifeExp)) + geom_point(aes(color = continent)) +
geom_smooth(method = "loess") +
scale_x_log10() +
labs(x =" Log GDP per Capita", y = "Life Expectancy") +
ggtitle("Association between GDP Per Capita and Life Expectancy") + theme(plot.title = element_text(lineheight = 0.8, face = "bold", hjust = 0.5)) + theme_economist()
## `geom_smooth()` using formula = 'y ~ x'
geom_smooth() using formula ‘y ~ x’Một số biểu đồ phổ biến khác sử dụng ggplot2 Biểu đồ histogram Đây còn được gọi là biểu đồ phân bố, sử dụng rất hữu ích khi thể hiện sự phân bố của một biến số liên tục nào đó. Trong bộ dữ liệu gapminder, thì biến gdpPercap là một biến số liên tục ngẫu nhiên, chúng ta thử vẽ biểu đồ histogram cho biến số này vào năm 2007. Sử dụng lệnh subset() đã học để bóc tách dữ liệu cho năm 2007
library(ggplot2)
library(gapminder)
year2007 <- subset(mydata, year == 2007)
head(year2007)
## # A tibble: 6 × 6
## country continent year lifeExp pop gdpPercap
## <fct> <fct> <int> <dbl> <int> <dbl>
## 1 Afghanistan Asia 2007 43.8 31889923 975.
## 2 Albania Europe 2007 76.4 3600523 5937.
## 3 Algeria Africa 2007 72.3 33333216 6223.
## 4 Angola Africa 2007 42.7 12420476 4797.
## 5 Argentina Americas 2007 75.3 40301927 12779.
## 6 Australia Oceania 2007 81.2 20434176 34435.
ggplot(data = year2007, mapping = aes(gdpPercap)) +
geom_histogram(fill = "lightblue", color = "white") +
labs(title = "Distribution of GDP per Capita in 2007")
## `stat_bin()` using `bins = 30`. Pick better value with `binwidth`.
Nếu chúng ta không muốn trục Oy là count mà muốn là xác suất (tần suất
xuất hiện)
ggplot(data = year2007, mapping = aes(gdpPercap)) +
geom_histogram(aes(y = ..density..), fill = "lightblue", color = "white")
## Warning: The dot-dot notation (`..density..`) was deprecated in ggplot2 3.4.0.
## ℹ Please use `after_stat(density)` instead.
## `stat_bin()` using `bins = 30`. Pick better value with `binwidth`.
##
stat_bin() using bins = 30. Pick better
value with binwidth.
Nếu chúng ta quan tâm phân phối theo từng lục địa
ggplot(data = year2007, mapping = aes(gdpPercap, fill = continent)) +
geom_density(alpha = 0.4)
Biểu đồ thanh Barplot Biểu đồ này thường được dùng để biểu thị tần số xuất hiện của 1 hay nhiều hơn 1 biến liên tục. Ví dụ: Chúng ta muốn tìm hiểu số quốc gia trong mỗi lục địa là bao nhiêu, sử dụng dữ liệu gapminder cho năm 2007.
dim(year2007)
## [1] 142 6
ggplot(data = year2007, mapping = aes(x = continent, fill = continent)) +
geom_bar() + theme(legend.position = "none")
Ngoài ra biểu đồ barplot còn thể hiện được sự liên quan giữa hai biến số
thông qua kiểu (stacked bar plot), biểu đồ thanh chồng lên nhau. Ví dụ
tuổi của các quốc gia có thể phân thành các nhóm sau đây:
Nhóm 1: Gồm các quốc gia có tuổi thọ dưới 60 Nhóm 2: Gồm các quốc gia có tuổi thọ lớn hơn 60 và nhỏ hơn 80 Nhóm 3: Gồm các quốc gia có tuổi thọ trên 80 Sử dụng toán tử điều kiện [] để tạo ra một biến mới tên là level_age có tính thứ bậc
year2007$level_age[year2007$lifeExp < 60.0] <- "< 60 age"
## Warning: Unknown or uninitialised column: `level_age`.
year2007$level_age[60.0 <= year2007$lifeExp & year2007$lifeExp <= 80.0] <- "60-80 age"
year2007$level_age[year2007$lifeExp > 80.0] <- "> 80 age"
ggplot(data = year2007, aes(x = continent, fill = level_age)) +
geom_bar()
Biểu đồ Barplot cũng có thể miêu tả một biến liên tục như sau. Ví dụ: Chúng ta muốn thể hiện tuổi thọ trung bình của mỗi quốc gia thuộc Châu Á (Asian). Trước tiên cần lọc các quốc gia có lục địa là Asian:
library(ggplot2)
asia <- subset(mydata, year == 2007 & continent == "Asia")
dim(asia)
## [1] 33 6
Như vậy ở Châu Á có 33 quốc gia. Trực quan dữ liệu
ggplot(data = asia, mapping = aes(x = country, y = lifeExp, fill = country)) + geom_bar(stat = "identity", width = 0.9)
Tuy nhiên giao diện rất khó nhìn và bị chồng lên nhau ở trục Ox, chúng ta đảo ngược
ggplot(data = asia, mapping = aes(x = country, y = lifeExp, fill = country)) + geom_bar(stat = "identity", width = 0.9) + coord_flip()
Biểu đồ này rất khó so sánh, chúng ta nên sắp xếp lại theo trật tự
ggplot(data = asia, mapping = aes(x = reorder(country, lifeExp), y = lifeExp, fill = country)) + geom_bar(stat = "identity", width = 0.9) + coord_flip() + theme(legend.position = "none") + labs(x="", y="Life Expectancy") -> graph1
Ngoài ra chúng ta có thể trình bày nhiều biểu đồ trên cùng một hình, sử dụng gói gridExtra, biểu diễn hai đồ thị thanh cho tuổi thọ và thu nhập bình quân đầu người
library(ggplot2)
library(gridExtra)
ggplot(data = asia, mapping = aes(x = reorder(country, gdpPercap), y = gdpPercap, fill = country)) + geom_bar(stat = "identity", width = 0.9) + coord_flip() + theme(legend.position = "none") + labs(x="", y="GDP Per Capita") -> graph2
grid.arrange(graph1, graph2, ncol = 2)
Biểu đồ hộp (Boxplot) Giới thiệu về biểu đồ hộp Biểu đồ hộp trong tiếng
Anh là Box Plot hay Box and Whisker plot, là một loại biểu đồ thể hiện
các khuôn hình của dữ liệu định tính (quantitative data). Biểu đồ hộp do
John Tukey sáng tạo ra năm 1977. Biểu đồ hộp (Box plot) hay còn gọi là
biểu đồ hộp và râu (Box and whisker plot) là biểu đồ diễn tả 5 vị trí
phân bố của dữ liệu, đó là: - Giá trị nhỏ nhất (min) - Giá trị tứ phân
vị thứ nhất (Q1) - Giá trị trung vị (median) - Giá trị tứ phân vị thứ 3
(Q3) - Giá trị lớn nhất (max)
John Tukey : “Đặt câu hỏi đúng quan trọng hơn ngàn lần tìm câu trả lời đúng cho một câu hỏi sai.”
Đặc trưng của biểu đồ hộp Số phân tử hay còn gọi là tứ phân vị (Quartiles): Tứ phân vị là đại lượng mô tả sự phân bố và sự phân tán của tập dữ liệu. Số phân tử có 3 giá trị, đó là số phân tử thứ nhất (Q1), thứ nhì (Q2) và thứ ba (Q3). Ba giá trị này chia một tập hợp dữ liệu (đã sắp xếp dữ liệu theo trật từ bé đến lớn) thành 4 phần có số lượng quan sát đều nhau.
Tứ phân vị được xác định như sau:
Sắp xếp các số theo thứ tự tăng dần
Cắt dãy số thành 4 phần bằng nhau
Tứ phân vị là các giá trị tại vị trí cắt
Khoảng biến thiên số phân tử (Interquartile Range - IQR) IQR được xác định như sau:
Biểu đồ boxplot còn thể hiện 2 đại lượng phổ biến khi nói về độ rộng của một tập dữ liệu:
Khoảng dữ liệu (range): Nếu bạn quan tâm đến độ rộng của tất cả dữ liệu thì, đó đơn giản là khoảng cách giữa giá trị lớn nhất và giá trị nhỏ nhất trong tập dữ liệu. Còn nếu bạn muốn loại trừ các giá trị ngoại lai, thì đó là khoảng cách giữa 2 đầu ria mép! Khoảng liên phần tư (IQR): là nửa giữa của tập dữ liệu nằm giữa 2 điểm Q3 và Q1. Trong biểu đồ trên, IQR là khoảng 7 – 3 = 4 Và cuối cùng, biểu đồ boxplots còn cung cấp thông tin cho chúng ta về hình dạng của tập dữ liệu:
Đây là 3 hình dạng chủ yếu về độ lệch. Nếu đường trung vị chia chiếc hộp thành 2 nửa đều nhau, thì tập dữ liệu này đối xứng (symmetric). Nếu nửa phải lớn hơn (nửa trái) thì tập dữ liệu bị lệch phải (right-skewed), và ngược lại, nếu nửa trái lớn hơn thì tập dữ liệu bị lệch trái (left-skewed).
Ví dụ Boxplot và cách đọc Dưới đây mô tả sử dụng biểu đồ hộp để phân tích, nhận biết vấn đề. Ví dụ: Với số liệu thu thập được về tỉ lệ làm lại (Rework Ratio) trong quá trình sản xuất, (có xmin = 0,0; Q1 = 14,9; x = 19,0; x = 15,8; Q3 = 20,6; xmax =23,2) ta có biểu đồ hộp với hình dáng biểu đồ như sau:
Trung bình tỉ lệ làm lại là 15,8%, trung vị là 19%. Dữ liệu có xu hướng nghiêng nhiều về phía trên giá trị trung bình:
Khoảng số phân tử = Q3 - Q1 = 20,6 - 14,9 = 5,7
Khoảng cách giữa giá trị lớn nhất và nhỏ nhất là 23,2 - 0 = 23,2. Nhìn chung, tỉ lệ làm lại cao và quá trình có sự dao động lớn, không ổn định, kiểm soát chất lượng kém. Tuy nhiên, biểu đồ hộp giúp nhìn trực quan hơn khi so sánh 3 giai đoạn hoặc khu vực khác nhau như hình dưới đây:
Nhận xét:
Với ba lần thu thập dữ liệu về tỉ lệ làm lại vào thời điểm tháng 11/2011, tháng 3/2012 và tháng 6/2012, dữ liệu vào thời điểm tháng 11/2011 cho thấy quá trình kiểm soát lỗi kém vì xu hướng tập trung của dữ liệu (trung vị) ở mức cao, độ dao động lớn.
Kiểm soát chất lượng vào thời điểm tháng 3/2012 là tốt nhất vì dữ liệu về tỉ lệ làm lại tập trung ở mức thấp, dao động ở phạm vi hẹp.
Áp dụng vào dữ liệu Giả sử chúng ta muốn tóm tắt thu nhập bình quân năm 2007 của 142 quốc gia bằng biểu đồ hộp
ggplot(data = year2007, aes(x = continent, y = gdpPercap, fill = continent)) + geom_boxplot(alpha = 0.6)
ggplot(data = year2007, aes(x = continent, y = gdpPercap, fill = continent)) + geom_boxplot(alpha = 0.6) + geom_jitter(alpha = 0.3)