1 Tuần 1 (30/5)

Thao tác trên dataset

data(trees)
d <- trees

str(d)
## 'data.frame':    31 obs. of  3 variables:
##  $ Girth : num  8.3 8.6 8.8 10.5 10.7 10.8 11 11 11.1 11.2 ...
##  $ Height: num  70 65 63 72 81 83 66 75 80 75 ...
##  $ Volume: num  10.3 10.3 10.2 16.4 18.8 19.7 15.6 18.2 22.6 19.9 ...
names(d) <- c('G','H','V')

Tới đây đã xong 1 số việc.

head(d)
##      G  H    V
## 1  8.3 70 10.3
## 2  8.6 65 10.3
## 3  8.8 63 10.2
## 4 10.5 72 16.4
## 5 10.7 81 18.8
## 6 10.8 83 19.7
vol <- d$V
vol
##  [1] 10.3 10.3 10.2 16.4 18.8 19.7 15.6 18.2 22.6 19.9 24.2 21.0 21.4 21.3 19.1
## [16] 22.2 33.8 27.4 25.7 24.9 34.5 31.7 36.3 38.3 42.6 55.4 55.7 58.3 51.5 51.0
## [31] 77.0
vol15 <- vol[vol>15 & vol<50]
vol15
##  [1] 16.4 18.8 19.7 15.6 18.2 22.6 19.9 24.2 21.0 21.4 21.3 19.1 22.2 33.8 27.4
## [16] 25.7 24.9 34.5 31.7 36.3 38.3 42.6
hei <- d$H
vol15hei60 <- d[d$V>15|d$H<60,]
vol15hei60
##       G  H    V
## 4  10.5 72 16.4
## 5  10.7 81 18.8
## 6  10.8 83 19.7
## 7  11.0 66 15.6
## 8  11.0 75 18.2
## 9  11.1 80 22.6
## 10 11.2 75 19.9
## 11 11.3 79 24.2
## 12 11.4 76 21.0
## 13 11.4 76 21.4
## 14 11.7 69 21.3
## 15 12.0 75 19.1
## 16 12.9 74 22.2
## 17 12.9 85 33.8
## 18 13.3 86 27.4
## 19 13.7 71 25.7
## 20 13.8 64 24.9
## 21 14.0 78 34.5
## 22 14.2 80 31.7
## 23 14.5 74 36.3
## 24 16.0 72 38.3
## 25 16.3 77 42.6
## 26 17.3 81 55.4
## 27 17.5 82 55.7
## 28 17.9 80 58.3
## 29 18.0 80 51.5
## 30 18.0 80 51.0
## 31 20.6 87 77.0
d$logV <- log(d$V)
d$logH <- log(d$H)
d$Tổng <- d$G+d$H+d$V

vol
##  [1] 10.3 10.3 10.2 16.4 18.8 19.7 15.6 18.2 22.6 19.9 24.2 21.0 21.4 21.3 19.1
## [16] 22.2 33.8 27.4 25.7 24.9 34.5 31.7 36.3 38.3 42.6 55.4 55.7 58.3 51.5 51.0
## [31] 77.0
cut(vol,4)
##  [1] (10.1,26.9] (10.1,26.9] (10.1,26.9] (10.1,26.9] (10.1,26.9] (10.1,26.9]
##  [7] (10.1,26.9] (10.1,26.9] (10.1,26.9] (10.1,26.9] (10.1,26.9] (10.1,26.9]
## [13] (10.1,26.9] (10.1,26.9] (10.1,26.9] (10.1,26.9] (26.9,43.6] (26.9,43.6]
## [19] (10.1,26.9] (10.1,26.9] (26.9,43.6] (26.9,43.6] (26.9,43.6] (26.9,43.6]
## [25] (26.9,43.6] (43.6,60.3] (43.6,60.3] (43.6,60.3] (43.6,60.3] (43.6,60.3]
## [31] (60.3,77.1]
## Levels: (10.1,26.9] (26.9,43.6] (43.6,60.3] (60.3,77.1]
table(cut(vol,4))
## 
## (10.1,26.9] (26.9,43.6] (43.6,60.3] (60.3,77.1] 
##          18           7           5           1

Bộ dữ liệu iris

data("iris")
cut(iris$Petal.Length,4)
##   [1] (0.994,2.48] (0.994,2.48] (0.994,2.48] (0.994,2.48] (0.994,2.48]
##   [6] (0.994,2.48] (0.994,2.48] (0.994,2.48] (0.994,2.48] (0.994,2.48]
##  [11] (0.994,2.48] (0.994,2.48] (0.994,2.48] (0.994,2.48] (0.994,2.48]
##  [16] (0.994,2.48] (0.994,2.48] (0.994,2.48] (0.994,2.48] (0.994,2.48]
##  [21] (0.994,2.48] (0.994,2.48] (0.994,2.48] (0.994,2.48] (0.994,2.48]
##  [26] (0.994,2.48] (0.994,2.48] (0.994,2.48] (0.994,2.48] (0.994,2.48]
##  [31] (0.994,2.48] (0.994,2.48] (0.994,2.48] (0.994,2.48] (0.994,2.48]
##  [36] (0.994,2.48] (0.994,2.48] (0.994,2.48] (0.994,2.48] (0.994,2.48]
##  [41] (0.994,2.48] (0.994,2.48] (0.994,2.48] (0.994,2.48] (0.994,2.48]
##  [46] (0.994,2.48] (0.994,2.48] (0.994,2.48] (0.994,2.48] (0.994,2.48]
##  [51] (3.95,5.43]  (3.95,5.43]  (3.95,5.43]  (3.95,5.43]  (3.95,5.43] 
##  [56] (3.95,5.43]  (3.95,5.43]  (2.48,3.95]  (3.95,5.43]  (2.48,3.95] 
##  [61] (2.48,3.95]  (3.95,5.43]  (3.95,5.43]  (3.95,5.43]  (2.48,3.95] 
##  [66] (3.95,5.43]  (3.95,5.43]  (3.95,5.43]  (3.95,5.43]  (2.48,3.95] 
##  [71] (3.95,5.43]  (3.95,5.43]  (3.95,5.43]  (3.95,5.43]  (3.95,5.43] 
##  [76] (3.95,5.43]  (3.95,5.43]  (3.95,5.43]  (3.95,5.43]  (2.48,3.95] 
##  [81] (2.48,3.95]  (2.48,3.95]  (2.48,3.95]  (3.95,5.43]  (3.95,5.43] 
##  [86] (3.95,5.43]  (3.95,5.43]  (3.95,5.43]  (3.95,5.43]  (3.95,5.43] 
##  [91] (3.95,5.43]  (3.95,5.43]  (3.95,5.43]  (2.48,3.95]  (3.95,5.43] 
##  [96] (3.95,5.43]  (3.95,5.43]  (3.95,5.43]  (2.48,3.95]  (3.95,5.43] 
## [101] (5.43,6.91]  (3.95,5.43]  (5.43,6.91]  (5.43,6.91]  (5.43,6.91] 
## [106] (5.43,6.91]  (3.95,5.43]  (5.43,6.91]  (5.43,6.91]  (5.43,6.91] 
## [111] (3.95,5.43]  (3.95,5.43]  (5.43,6.91]  (3.95,5.43]  (3.95,5.43] 
## [116] (3.95,5.43]  (5.43,6.91]  (5.43,6.91]  (5.43,6.91]  (3.95,5.43] 
## [121] (5.43,6.91]  (3.95,5.43]  (5.43,6.91]  (3.95,5.43]  (5.43,6.91] 
## [126] (5.43,6.91]  (3.95,5.43]  (3.95,5.43]  (5.43,6.91]  (5.43,6.91] 
## [131] (5.43,6.91]  (5.43,6.91]  (5.43,6.91]  (3.95,5.43]  (5.43,6.91] 
## [136] (5.43,6.91]  (5.43,6.91]  (5.43,6.91]  (3.95,5.43]  (3.95,5.43] 
## [141] (5.43,6.91]  (3.95,5.43]  (3.95,5.43]  (5.43,6.91]  (5.43,6.91] 
## [146] (3.95,5.43]  (3.95,5.43]  (3.95,5.43]  (3.95,5.43]  (3.95,5.43] 
## Levels: (0.994,2.48] (2.48,3.95] (3.95,5.43] (5.43,6.91]
table(cut(iris$Petal.Length,4))
## 
## (0.994,2.48]  (2.48,3.95]  (3.95,5.43]  (5.43,6.91] 
##           50           11           61           28
table(cut(iris$Petal.Length,4),iris$Species)
##               
##                setosa versicolor virginica
##   (0.994,2.48]     50          0         0
##   (2.48,3.95]       0         11         0
##   (3.95,5.43]       0         39        22
##   (5.43,6.91]       0          0        28

2 Tuần 2 (6/6)

setosa <- iris[iris$Species == 'setosa',]
nosetosa <- iris[!iris$Species == 'setosa',]
iris$slcoded <- cut(iris$Sepal.Length, breaks = c(4.3,4.8,7.2,7.9),labels = c('ngắn', 'vừa', 'dài'))
table(iris$slcoded)
## 
## ngắn  vừa  dài 
##   15  126    8
# Tính các đơn vị tính toán 
summary(iris$Sepal.Length)
##    Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
##   4.300   5.100   5.800   5.843   6.400   7.900
mean(iris$Sepal.Length)
## [1] 5.843333
var(iris$Sepal.Length)
## [1] 0.6856935
sd(iris$Sepal.Length)
## [1] 0.8280661
sum(iris$Sepal.Length)
## [1] 876.5
median(iris$Sepal.Length)
## [1] 5.8
###(Chọn ngẫu nhiên để tìm ra xác suất nhở hơn 5.1 là 25%)
quantile(iris$Sepal.Length) 
##   0%  25%  50%  75% 100% 
##  4.3  5.1  5.8  6.4  7.9
quantile(iris$Sepal.Length,.3) 
##  30% 
## 5.27
table(iris$Species)
## 
##     setosa versicolor  virginica 
##         50         50         50
### Tính phương sai, trung bình có điều kiện
aggregate(iris$Sepal.Length, list(iris$Species), FUN = 'mean')
##      Group.1     x
## 1     setosa 5.006
## 2 versicolor 5.936
## 3  virginica 6.588
aggregate(iris$Sepal.Length, list(iris$Species), FUN = 'sd')
##      Group.1         x
## 1     setosa 0.3524897
## 2 versicolor 0.5161711
## 3  virginica 0.6358796
aggregate(iris$Sepal.Length, list(iris$slcoded), FUN = 'mean')
##   Group.1        x
## 1    ngắn 4.633333
## 2     vừa 5.886508
## 3     dài 7.625000
aggregate(iris$Sepal.Length, list(iris$Species), FUN = 'summary')
##      Group.1 x.Min. x.1st Qu. x.Median x.Mean x.3rd Qu. x.Max.
## 1     setosa  4.300     4.800    5.000  5.006     5.200  5.800
## 2 versicolor  4.900     5.600    5.900  5.936     6.300  7.000
## 3  virginica  4.900     6.225    6.500  6.588     6.900  7.900
library(tidyverse)
## ── Attaching core tidyverse packages ──────────────────────── tidyverse 2.0.0 ──
## ✔ dplyr     1.1.2     ✔ readr     2.1.4
## ✔ forcats   1.0.0     ✔ stringr   1.5.0
## ✔ ggplot2   3.4.2     ✔ tibble    3.2.1
## ✔ lubridate 1.9.2     ✔ tidyr     1.3.0
## ✔ purrr     1.0.1     
## ── Conflicts ────────────────────────────────────────── tidyverse_conflicts() ──
## ✖ dplyr::filter() masks stats::filter()
## ✖ dplyr::lag()    masks stats::lag()
## ℹ Use the conflicted package (<http://conflicted.r-lib.org/>) to force all conflicts to become errors
library(ggplot2)
library(utf8)

### Lệnh mới để tính như trên ( ctrl + shilf + M <- %>% )
iris %>% group_by(Species)
## # A tibble: 150 × 6
## # Groups:   Species [3]
##    Sepal.Length Sepal.Width Petal.Length Petal.Width Species slcoded
##           <dbl>       <dbl>        <dbl>       <dbl> <fct>   <fct>  
##  1          5.1         3.5          1.4         0.2 setosa  vừa    
##  2          4.9         3            1.4         0.2 setosa  vừa    
##  3          4.7         3.2          1.3         0.2 setosa  ngắn   
##  4          4.6         3.1          1.5         0.2 setosa  ngắn   
##  5          5           3.6          1.4         0.2 setosa  vừa    
##  6          5.4         3.9          1.7         0.4 setosa  vừa    
##  7          4.6         3.4          1.4         0.3 setosa  ngắn   
##  8          5           3.4          1.5         0.2 setosa  vừa    
##  9          4.4         2.9          1.4         0.2 setosa  ngắn   
## 10          4.9         3.1          1.5         0.1 setosa  vừa    
## # ℹ 140 more rows
data("iris")
tmp <- iris
str(tmp)
## 'data.frame':    150 obs. of  5 variables:
##  $ Sepal.Length: num  5.1 4.9 4.7 4.6 5 5.4 4.6 5 4.4 4.9 ...
##  $ Sepal.Width : num  3.5 3 3.2 3.1 3.6 3.9 3.4 3.4 2.9 3.1 ...
##  $ Petal.Length: num  1.4 1.4 1.3 1.5 1.4 1.7 1.4 1.5 1.4 1.5 ...
##  $ Petal.Width : num  0.2 0.2 0.2 0.2 0.2 0.4 0.3 0.2 0.2 0.1 ...
##  $ Species     : Factor w/ 3 levels "setosa","versicolor",..: 1 1 1 1 1 1 1 1 1 1 ...
names(tmp) <- c('SL','SW','PL','PW','Sp')


tmp %>% group_by(Sp) %>% summarise(m = mean(SL))
## # A tibble: 3 × 2
##   Sp             m
##   <fct>      <dbl>
## 1 setosa      5.01
## 2 versicolor  5.94
## 3 virginica   6.59
tmp %>% group_by(Sp) %>% summarise(m = mean(SL), n=sd(SL))
## # A tibble: 3 × 3
##   Sp             m     n
##   <fct>      <dbl> <dbl>
## 1 setosa      5.01 0.352
## 2 versicolor  5.94 0.516
## 3 virginica   6.59 0.636

2.1 Mô phỏng dữ liệu

### Phân loại dữ liệu từ nhìu người thu thập
poi2 <- rpois(10,2)
poi2
##  [1] 2 3 4 2 2 1 1 1 1 3
poi4 <- rpois(100,4)
bi <- rbinom(100,15,.4)
ge <- rgeom(100,.3)
no <- rnorm(100,9,2)

### Kiểm tra có phải là vecto ko?
is.vector(poi2)
## [1] TRUE
### Chuyển Vecto thành 1 data frame
poi2 <- as.data.frame(poi2)



### Tạo 1 dãy số khác
tg <- seq(2,2, length = 10)
tg
##  [1] 2 2 2 2 2 2 2 2 2 2
poi2$tg <- tg



### Tạo 1 bảng dữ liệu từ những dữ liệu khác nhau
d1 <- rpois(10,6)
d2 <- rnorm(10,6,2)
d3 <- rnorm(10,15,2)

### Gán giá trị cho từng biến
d1 <- as.data.frame(d1)
d1$tg <- seq(1,1, length = 10)
d2 <- as.data.frame(d2)
d2$tg <- seq(2,2, length=10)
d3 <- as.data.frame(d3)
d3$tg <- seq(3,3, length=10)

### Đưa vào chung 1 data
names(d1) <- c('D','tg')
names(d2) <- c('D','tg')
names(d3) <- c('D','tg')

tonghop <- rbind(d1, d2, d3)

3 Tuần 3 (13/6)

3.1 Giới thiệu Rmarkdown Syntax

3.2 Pivot table

  • Longer
  • Wider

3.3 Thao tác dữ liệu trên billboard

3.3.1 Pivot_table (LONGER)

library(tidyverse)
data("billboard")
bill <- billboard

# Chuyển tệp có độ rộng từ 79 biến 317 số liệu thành tệp 5 biến 24092 dữ liệu(cụ thể ghép các cột wk lại với nhau)
tmp <- bill |> pivot_longer(cols=starts_with('wk'), names_to = 'week',values_to = 'rank')

# Dữ liệu ko khả thi thì dùng thêm dòng values_drop_na = T để loại bỏ các biến N/A
tmp <- bill |> pivot_longer(cols=starts_with('wk'), names_to = 'week',values_to = 'rank', values_drop_na = T)

#Lệnh kếp=t hợp từ câu lệnh trên với lệnh mutate tạo 1 lệnh mới ( lệnh parse_number() chỉ dùng để lấy số trong 1 cột dữ liệu nào đó)
tmp <- bill |> pivot_longer(cols=starts_with('wk'), names_to = 'week',values_to = 'rank', values_drop_na = T)|> mutate(week=parse_number(week))

#3 cách để tạo ra một cột mới 
tmp$aa <- seq(1,1,length(tmp$artist)) 
tmp$bb <-  mutate(tmp,bb=tmp$rank+tmp$aa)
tmp$cc <-  tmp %>% mutate(bb=rank+aa)

tmp
## # A tibble: 5,307 × 8
##    artist  track              date.entered  week  rank    aa bb$artist cc$artist
##    <chr>   <chr>              <date>       <dbl> <dbl> <dbl> <chr>     <chr>    
##  1 2 Pac   Baby Don't Cry (K… 2000-02-26       1    87     1 2 Pac     2 Pac    
##  2 2 Pac   Baby Don't Cry (K… 2000-02-26       2    82     1 2 Pac     2 Pac    
##  3 2 Pac   Baby Don't Cry (K… 2000-02-26       3    72     1 2 Pac     2 Pac    
##  4 2 Pac   Baby Don't Cry (K… 2000-02-26       4    77     1 2 Pac     2 Pac    
##  5 2 Pac   Baby Don't Cry (K… 2000-02-26       5    87     1 2 Pac     2 Pac    
##  6 2 Pac   Baby Don't Cry (K… 2000-02-26       6    94     1 2 Pac     2 Pac    
##  7 2 Pac   Baby Don't Cry (K… 2000-02-26       7    99     1 2 Pac     2 Pac    
##  8 2Ge+her The Hardest Part … 2000-09-02       1    91     1 2Ge+her   2Ge+her  
##  9 2Ge+her The Hardest Part … 2000-09-02       2    87     1 2Ge+her   2Ge+her  
## 10 2Ge+her The Hardest Part … 2000-09-02       3    92     1 2Ge+her   2Ge+her  
## # ℹ 5,297 more rows
## # ℹ 12 more variables: bb$track <chr>, $date.entered <date>, $week <dbl>,
## #   $rank <dbl>, $aa <dbl>, $bb <dbl>, cc$track <chr>, $date.entered <date>,
## #   $week <dbl>, $rank <dbl>, $aa <dbl>, $bb <dbl>

3.4 Thao tác trên tệp dữ liệu VerbAgg

3.4.1 Pivot_table(WIDER)

library(lme4)
## Loading required package: Matrix
## 
## Attaching package: 'Matrix'
## The following objects are masked from 'package:tidyr':
## 
##     expand, pack, unpack
data(VerbAgg)
levels(VerbAgg$item)
##  [1] "S1WantCurse" "S1WantScold" "S1WantShout" "S2WantCurse" "S2WantScold"
##  [6] "S2WantShout" "S3WantCurse" "S3WantScold" "S3WantShout" "S4wantCurse"
## [11] "S4WantScold" "S4WantShout" "S1DoCurse"   "S1DoScold"   "S1DoShout"  
## [16] "S2DoCurse"   "S2DoScold"   "S2DoShout"   "S3DoCurse"   "S3DoScold"  
## [21] "S3DoShout"   "S4DoCurse"   "S4DoScold"   "S4DoShout"
summary(VerbAgg)
##      Anger    Gender            item           resp            id      
##  Min.   :11   F:5832   S1WantCurse: 316   no     :3973   1      :  24  
##  1st Qu.:17   M:1752   S1WantScold: 316   perhaps:2081   2      :  24  
##  Median :19            S1WantShout: 316   yes    :1530   3      :  24  
##  Mean   :20            S2WantCurse: 316                  4      :  24  
##  3rd Qu.:23            S2WantScold: 316                  5      :  24  
##  Max.   :39            S2WantShout: 316                  6      :  24  
##                        (Other)    :5688                  (Other):7440  
##    btype         situ        mode      r2      
##  curse:2528   other:3792   want:3792   N:3973  
##  scold:2528   self :3792   do  :3792   Y:3611  
##  shout:2528                                    
##                                                
##                                                
##                                                
## 
# Thêm 1 cột mới có điều kiện
VerbAgg <- VerbAgg %>% mutate(respn=case_when(resp=="no"~0,resp=="perhaps"~1,resp=="yes"~1))
table(VerbAgg$respn)
## 
##    0    1 
## 3973 3611
# Cách chuyển tệp có độ dài thành tệp có nhiều cột
resp_wide <- VerbAgg %>% select(id, item, resp) %>% pivot_wider(names_from = item, values_from = resp)

#Tạo ra một tệp mới có những biến theo yêu cầu
tmp <- VerbAgg %>% select(id, item, respn)

4 Tuần 4 (20/6)

4.1 Data visualize ( mượn hình ảnh để trình bày dữ liệu)ư

4.2 Giới thiệu về gói GGPLOT2

4.2.1 ĐÒ thị dạng Scatter ( thường dùng cho dữ liệu định lượng)

Thực hiện mở bảng data.table

library(ggplot2)
data("trees")
data.table::data.table(trees)
##     Girth Height Volume
##  1:   8.3     70   10.3
##  2:   8.6     65   10.3
##  3:   8.8     63   10.2
##  4:  10.5     72   16.4
##  5:  10.7     81   18.8
##  6:  10.8     83   19.7
##  7:  11.0     66   15.6
##  8:  11.0     75   18.2
##  9:  11.1     80   22.6
## 10:  11.2     75   19.9
## 11:  11.3     79   24.2
## 12:  11.4     76   21.0
## 13:  11.4     76   21.4
## 14:  11.7     69   21.3
## 15:  12.0     75   19.1
## 16:  12.9     74   22.2
## 17:  12.9     85   33.8
## 18:  13.3     86   27.4
## 19:  13.7     71   25.7
## 20:  13.8     64   24.9
## 21:  14.0     78   34.5
## 22:  14.2     80   31.7
## 23:  14.5     74   36.3
## 24:  16.0     72   38.3
## 25:  16.3     77   42.6
## 26:  17.3     81   55.4
## 27:  17.5     82   55.7
## 28:  17.9     80   58.3
## 29:  18.0     80   51.5
## 30:  18.0     80   51.0
## 31:  20.6     87   77.0
##     Girth Height Volume
trees 
##    Girth Height Volume
## 1    8.3     70   10.3
## 2    8.6     65   10.3
## 3    8.8     63   10.2
## 4   10.5     72   16.4
## 5   10.7     81   18.8
## 6   10.8     83   19.7
## 7   11.0     66   15.6
## 8   11.0     75   18.2
## 9   11.1     80   22.6
## 10  11.2     75   19.9
## 11  11.3     79   24.2
## 12  11.4     76   21.0
## 13  11.4     76   21.4
## 14  11.7     69   21.3
## 15  12.0     75   19.1
## 16  12.9     74   22.2
## 17  12.9     85   33.8
## 18  13.3     86   27.4
## 19  13.7     71   25.7
## 20  13.8     64   24.9
## 21  14.0     78   34.5
## 22  14.2     80   31.7
## 23  14.5     74   36.3
## 24  16.0     72   38.3
## 25  16.3     77   42.6
## 26  17.3     81   55.4
## 27  17.5     82   55.7
## 28  17.9     80   58.3
## 29  18.0     80   51.5
## 30  18.0     80   51.0
## 31  20.6     87   77.0
trees |> ggplot(map = aes(x = Girth, y = Volume)) +
  geom_point(color = 'red')

trees |> ggplot(map = aes(x = Girth, y = Volume)) +
  geom_point(color = 'red') +
  xlab('Chu vi') +
  ylab('Thể tích')

Trong trường hợp cần thiết chúng ta có thể vẽ thêm đường hồi quy (tuyến tính) tương ứng với dữ liệu mà chúng ta dùng để vẽ đồ thị scatter như sau:

trees |> ggplot(aes(x = Girth, y = Volume))+
  geom_smooth(formula = y ~ x, method = 'lm', color = 'green') +
  geom_point(color = 'red') +
  labs(title = 'Đồ Thị Dạng Scatter', x = 'Chu vi', y = 'Thể tích')

húng ta cũng có thể nối các điểm trong đồ thị dạng scatter của 2 biến Girth và Volume lại với nhau bằng những đoạn thẳng như sau:

trees |> ggplot(aes(x = Girth, y = Volume)) +
  geom_point(color = 'blue') +
  geom_line(color = 'red')

4.3 Thực hành trên package và data penguin

Để mở rộng việc sử dụng đồ thị dạng scatter chúng ta sẽ gọi bộ dữ liệu penguins trong package palmerpenguins. Bộ dữ liệu này được các nhà khoa học thu thập nhằm mục đích nghiên cứu về các loài chim cánh cụt ở Nam cực.

Để có thể thấy được tương quan giữa biến flipper_length_mm và biến body_mass_g, chúng ta sẽ vẽ đồ thị dạng scatter cho 2 biến này như sau:

library(palmerpenguins)
data("penguins")
data.table::data.table(penguins)
##        species    island bill_length_mm bill_depth_mm flipper_length_mm
##   1:    Adelie Torgersen           39.1          18.7               181
##   2:    Adelie Torgersen           39.5          17.4               186
##   3:    Adelie Torgersen           40.3          18.0               195
##   4:    Adelie Torgersen             NA            NA                NA
##   5:    Adelie Torgersen           36.7          19.3               193
##  ---                                                                   
## 340: Chinstrap     Dream           55.8          19.8               207
## 341: Chinstrap     Dream           43.5          18.1               202
## 342: Chinstrap     Dream           49.6          18.2               193
## 343: Chinstrap     Dream           50.8          19.0               210
## 344: Chinstrap     Dream           50.2          18.7               198
##      body_mass_g    sex year
##   1:        3750   male 2007
##   2:        3800 female 2007
##   3:        3250 female 2007
##   4:          NA   <NA> 2007
##   5:        3450 female 2007
##  ---                        
## 340:        4000   male 2009
## 341:        3400 female 2009
## 342:        3775   male 2009
## 343:        4100   male 2009
## 344:        3775 female 2009
penguins |> ggplot(aes(x = flipper_length_mm, y = body_mass_g)) + 
  geom_point(na.rm = T) +
  xlab('Chiều dài cánh') +
  ylab('Trọng lượng cơ thể')

Tuy nhiên chúng ta còn có thể có cái nhìn sâu hơn về tương quan giữa 2 biến này theo loài hoặc theo nơi chúng sinh sống như sau:

penguins |> ggplot(aes(x = flipper_length_mm, y = body_mass_g, color = species)) + 
  geom_point(na.rm = T) +
  xlab('Chiều dài cánh') +
  ylab('Trọng lượng cơ thể')

penguins |> ggplot(aes(x = flipper_length_mm, y = body_mass_g)) + 
  geom_point(aes(color = island), na.rm = T) +
  xlab('Chiều dài cánh') +
  ylab('Trọng lượng cơ thể')

Ngoài việc phân loại dữ liệu bằng màu sắc chúng ta còn có thể phân biệt dữ liệu bằng hình dáng như sau:

penguins |> ggplot(aes(x = flipper_length_mm, y = body_mass_g)) + 
  geom_point(aes(shape = island), na.rm = T, color = 'blue', size = 3) +
  xlab('Chiều dài cánh') +
  ylab('Trọng lượng cơ thể')

Đôi khi chúng ta quan tâm đến một số quan sát đặc biệt nào đó, chúng ta có thể tạo một sự khác biệt để có thể nhận biết được biết được các quan sát này dễ hơn. Điều này được thực hiện như sau:

penguins |> ggplot(aes(x = flipper_length_mm, y = body_mass_g, shape = island)) + 
  geom_point(na.rm = T, size = 3) +
  geom_point(data = penguins |> filter(sex == 'male'), color = 'red') +
  xlab('Chiều dài cánh') +
  ylab('Trọng lượng cơ thể')

Chúng ta cũng có thể thêm hàm hồi quy (tuyến tính) vào đồ thị scatter như ví dụ bên trên, tuy nhiên chúng ta còn có thể thêm được nhiều hàm hồi quy (tuyến tính) tương ứng với từng loài hoặc tương ứng với nhiều nơi sinh sống như sau:

penguins |> ggplot(aes(x = flipper_length_mm, y = body_mass_g)) + 
  geom_point(aes(color = species), na.rm = T) +
  geom_smooth(aes(color = species), formula = y ~ x, method = 'lm', na.rm = T) +
  xlab('Chiều dài cánh') +
  ylab('Trọng lượng cơ thể')

penguins |> ggplot(aes(x = flipper_length_mm, y = body_mass_g)) + 
  geom_point(aes(color = island), na.rm = T) +
  geom_smooth(aes(color = island), formula = y ~ x, method = 'lm', na.rm = T) +
  xlab('Chiều dài cánh') +
  ylab('Trọng lượng cơ thể')

Hoặc chúng ta có thể vẽ thành nhiều đồ thị tương ứng với từng loài hoặc từng nơi sinh sống như sau:

penguins |> ggplot(aes(x = flipper_length_mm, y = body_mass_g)) +
  geom_point(aes(color = species), na.rm = T) +
  geom_smooth(formula =  y ~ x, method = 'lm', na.rm = T) +
  facet_grid(. ~ species) +
  xlab('Chiều dài cánh') +
  ylab('Trọng lượng cơ thể')

penguins |> ggplot(aes(x = flipper_length_mm, y = body_mass_g)) +
  geom_point(aes(color = island), na.rm = T) +
  geom_smooth(formula =  y ~ x, method = 'lm', na.rm = T) +
  facet_grid(. ~ island) +
  xlab('Chiều dài cánh') +
  ylab('Trọng lượng cơ thể')

Hoặc chúng ta có thể xắp xếp các đồ thị này theo phương dọc như sau:

penguins |> ggplot(aes(x = flipper_length_mm, y = body_mass_g)) +
  geom_point(aes(color = island), na.rm = T) +
  geom_smooth(formula =  y ~ x, method = 'lm', na.rm = T) +
  facet_grid(island ~ .) +
  xlab('Chiều dài cánh') +
  ylab('Trọng lượng cơ thể')

4.4 Biểu đồ cột

thực hiện trên file excel mới có tên lá Supermarket transactions

d <- read.csv('Supermarket Transactions.csv', header = T)
str(d)
## 'data.frame':    14059 obs. of  16 variables:
##  $ X                : int  1 2 3 4 5 6 7 8 9 10 ...
##  $ PurchaseDate     : chr  "18/12/2007" "20/12/2007" "21/12/2007" "21/12/2007" ...
##  $ CustomerID       : int  7223 7841 8374 9619 1900 6696 9673 354 1293 7938 ...
##  $ Gender           : chr  "F" "M" "F" "M" ...
##  $ MaritalStatus    : chr  "S" "M" "M" "M" ...
##  $ Homeowner        : chr  "Y" "Y" "N" "Y" ...
##  $ Children         : int  2 5 2 3 3 3 2 2 3 1 ...
##  $ AnnualIncome     : chr  "$30K - $50K" "$70K - $90K" "$50K - $70K" "$30K - $50K" ...
##  $ City             : chr  "Los Angeles" "Los Angeles" "Bremerton" "Portland" ...
##  $ StateorProvince  : chr  "CA" "CA" "WA" "OR" ...
##  $ Country          : chr  "USA" "USA" "USA" "USA" ...
##  $ ProductFamily    : chr  "Food" "Food" "Food" "Food" ...
##  $ ProductDepartment: chr  "Snack Foods" "Produce" "Snack Foods" "Snacks" ...
##  $ ProductCategory  : chr  "Snack Foods" "Vegetables" "Snack Foods" "Candy" ...
##  $ UnitsSold        : int  5 5 3 4 4 3 4 6 1 2 ...
##  $ Revenue          : num  27.38 14.9 5.52 4.44 14 ...
data.table::data.table(d)
##            X PurchaseDate CustomerID Gender MaritalStatus Homeowner Children
##     1:     1   18/12/2007       7223      F             S         Y        2
##     2:     2   20/12/2007       7841      M             M         Y        5
##     3:     3   21/12/2007       8374      F             M         N        2
##     4:     4   21/12/2007       9619      M             M         Y        3
##     5:     5   22/12/2007       1900      F             S         Y        3
##    ---                                                                      
## 14055: 14055   29/12/2009       9102      F             M         Y        2
## 14056: 14056   29/12/2009       4822      F             M         Y        3
## 14057: 14057   31/12/2009        250      M             S         Y        1
## 14058: 14058   31/12/2009       6153      F             S         N        4
## 14059: 14059   31/12/2009       3656      M             S         N        3
##         AnnualIncome          City StateorProvince Country  ProductFamily
##     1:   $30K - $50K   Los Angeles              CA     USA           Food
##     2:   $70K - $90K   Los Angeles              CA     USA           Food
##     3:   $50K - $70K     Bremerton              WA     USA           Food
##     4:   $30K - $50K      Portland              OR     USA           Food
##     5: $130K - $150K Beverly Hills              CA     USA          Drink
##    ---                                                                   
## 14055:   $10K - $30K     Bremerton              WA     USA           Food
## 14056:   $10K - $30K   Walla Walla              WA     USA           Food
## 14057:   $30K - $50K      Portland              OR     USA          Drink
## 14058:   $50K - $70K       Spokane              WA     USA          Drink
## 14059:   $50K - $70K      Portland              OR     USA Non-Consumable
##        ProductDepartment      ProductCategory UnitsSold Revenue
##     1:       Snack Foods          Snack Foods         5   27.38
##     2:           Produce           Vegetables         5   14.90
##     3:       Snack Foods          Snack Foods         3    5.52
##     4:            Snacks                Candy         4    4.44
##     5:         Beverages Carbonated Beverages         4   14.00
##    ---                                                         
## 14055:      Baking Goods         Baking Goods         3    9.64
## 14056:      Frozen Foods           Vegetables         3    7.45
## 14057:         Beverages Pure Juice Beverages         4    3.24
## 14058:             Dairy                Dairy         2    4.00
## 14059:         Household           Electrical         5   25.53

Chúng ta sẽ đồ thị cột cho biến Gender.

d |> ggplot(aes(x = Gender )) +
  geom_bar( fill = 'blue')

Thay vì thể hiện bằng số đếm thì chúng ta có thể thì chúng ta sẽ thể hiện bằng tỉ lệ % như sau:

d |> ggplot(aes(x = Gender )) +
  geom_bar(aes(y = after_stat(100*count/sum(count))), fill = 'blue') +
  theme_classic() +
  labs(x = 'Giới tính', y = 'Tỷ lệ %')

Chúng ta có thể ghi chú tỷ lệ % hoặc số đếm lên đỉnh mỗi cột như sau:

library(scales)
## 
## Attaching package: 'scales'
## The following object is masked from 'package:purrr':
## 
##     discard
## The following object is masked from 'package:readr':
## 
##     col_factor
d |> ggplot(aes(x = Gender, y = after_stat(count))) +
  geom_bar(fill = 'blue') +
  geom_text(aes(label = scales::percent(after_stat(count/sum(count)))), stat = 'count', color = 'red', vjust = - .5) +
  theme_classic() +
  labs(x = 'Giới tính', y = 'Số người')

Chúng ta có thể vẽ biểu đồ cột cho biến Children như sau:

d |> count(Children) |>
  mutate(pC = percent(n/sum(n),accuracy = 0.01)) |>
  ggplot(aes(x = Children, y = n)) +
  geom_col(fill = 'blue') +
  geom_text(aes(label = pC),color = 'yellow', vjust = 2, size = 5) +
  ylab('Số Người') +
  xlab('Số Con')

Với biểu đồ như trên chúng ta có thể quay ngang như sau:

d |> count(Children) |>
  mutate(pC = percent(n/sum(n),accuracy = 0.01)) |>
  ggplot(aes(x = Children, y = n)) +
  geom_col(fill = 'blue') +
  geom_text(aes(label = pC),color = 'yellow', hjust = 2, size = 5) +
  ylab('Số Người') +
  xlab('Số Con') +
  coord_flip()

Chúng ta cũng có thể vẽ đồ thi dạng cột theo biến Children nhưng đồng thời chúng ta sẽ phân đồ thì này thành 2 nhóm theo biến Homeowner như sau:

d |> ggplot(aes(x = Children, y = after_stat(count),fill = Homeowner)) +
  geom_bar(position = 'dodge') +
  ylab('Số Người') +
  xlab('Số Con')

húng ta có thể thêm ghi chú cho đồ thị để người đọc dễ so sánh như sau:

d |> count(Children, Homeowner) |>
  mutate(pCH = prop.table(n)) |>
  ggplot(aes(x = Children, y = n, fill = Homeowner)) +
  geom_col(position = 'dodge') +
  geom_text(aes(label = percent(pCH, accuracy = .01)), position = position_dodge(1), vjust = -.5) +
  ylab('Số Người') +
  xlab('Số Con')

Với dạng đồ thị như trên thay vì để 2 cột cạnh nhau, chúng ta có thể chồng nó lên nhau như sau đ`ể dễ phân tích hơn.

d |> ggplot(aes(x = Children)) +
  geom_bar(aes(y = after_stat(count), fill = Homeowner), stat = 'count') +
  ylab('Số Người') +
  xlab('Số Con')

Tương tự như trường hợp ở trên, chúng ta cũng có thể thêm ghi chú và đồ thị để người đọc dễ so sánh như sau:

d |> count(Children, Homeowner) |>
  group_by(Children) |>
  mutate(pH = n/sum(n)) |>
  ggplot(aes(x = Children, y = n, fill = Homeowner)) +
  geom_col() +
  geom_text(aes(label = percent(pH, accuracy = .01)), position = position_stack(vjust = 0.5)) +
  ylab('Số Người') +
  xlab('Số Con')

Với biểu đồ cột chúng ta còn có thể làm được nhiều việc hơn những gì chúng ta đã làm bên trên. Ví dụ chúng ta sẽ vẽ đồ thị thể hiện số tiền trung bình của hóa đơn theo giới tính hoặc theo số con như sau:

d |> group_by(Gender) |> 
  summarise(mr = mean(Revenue, na.rm = T)) |> 
  ggplot(aes(x = Gender, y = mr)) +
  geom_col(fill = 'blue') +
  geom_text(aes(label = round(mr,2)), vjust = 2, color = 'red', size = 9)

d |> group_by(Children) |> 
  summarise(mr = mean(Revenue, na.rm = T)) |> 
  ggplot(aes(x = Children, y = mr)) +
  geom_col(fill = 'blue') +
  geom_text(aes(label = round(mr,2)), vjust = 2, color = 'red', size = 5)

Tương tự chúng ta cũng có thể dùng đồ thị cột để vẽ phương sai, độ lệch chuẩn, trung vị hay bất kỳ một đặc trưng thống kê nào để thực hiện việc so sánh. Ví dụ:

d |> group_by(Children) |> 
  summarise(vr = var(Revenue, na.rm = T)) |> 
  ggplot(aes(x = Children, y = vr)) +
  geom_bar(stat = 'identity', fill = 'blue') +
  geom_text(aes(y = vr + 3, label = round(vr,2)), color = 'red', size = 6)

Chúng ta cũng có thể Vẽ đồ thị dạng cột để so sánh số tiền trên hóa đơn theo biến Gender và biến Children như sau:

d |> group_by(Children, Homeowner) |> 
  summarise(mCH = mean(Revenue, na.rm = T)) |> 
  ggplot(aes(x = Children, y = mCH, fill = Homeowner)) +
  geom_col(position = 'dodge') +
  geom_text(aes(y = mCH + 2, label = round(mCH,1)), position = position_dodge(1), vjust = 3)
## `summarise()` has grouped output by 'Children'. You can override using the
## `.groups` argument.