1 Nguồn dữ liệu

https://drive.google.com/file/d/1LXQWYeCZa1bkj1k02bwqevxcmi1MhGNk/view?usp=sharing

library(tidyverse)
library(AER)
library(DT)
getwd()
## [1] "C:/Users/PHUONG UYEN"
setwd("C:/Users/PHUONG UYEN")
data <- read_csv("C:/Users/PHUONG UYEN/datasetusedcars.csv")
d <- data
d <- na.omit(d)

Đọc dữ liệu

2 Mô tả bộ dữ liệu

  • Mô tả: Bộ dữ liệu về hơn 100000 chiếc ô tô đã qua sử dụng ở Vương Quốc Anh
  • Make: Dòng xe đã qua sử dụng
  • Model: Loại lốp xe mà xe đó sử dụng
  • Name: Tên loại xe
  • Price: Giá của chiếc xe đó
  • Year: Năm sản xuất
  • Miles: Khoảng cách mà xe đã đi được
  • BHP(brake horsepower): Công suất thực tế mà động cơ có thể cung cấp.
  • L(Litre): đo lường dung tích nhiên liệu của xe
  • Trans(Transmission): Loại hộp số
  • Fuel: Nhiên liệu mà xe sử dụng

3 Phân tích dữ liệu

3.1 Lọc dữ liệu với filter()

d %>% filter(Model == '124 Spider') %>% datatable()
  • Lọc thông tin của những chiếc xe sử dụng loại lốp xe là 124 Spider
d %>% filter( Make== "Abarth", BHP > 50) %>% datatable()
  • Lọc ra thông tin của những dòng xe có tên là Abarth và có công suất lớn hơn 50W.

d %>% filter(Make == "Audi", Year == 2017) %>% datatable()
  • Lọc ra những dòng xe Audi và có năm sản xuất là 2017.

3.2 Mã hoá số liệu với case_match() và case_when()

d$groupyear <- cut(d$Year, breaks = c(1960,1980,2000,2010,2020), labels = c("60_nam_truoc","40_nam_truoc","20_nam_truoc","10_nam_truoc"))
  • Tạo cột mới tên là groupyear, chứa thông tin về nhóm mà mỗi năm thuộc vào dựa trên khoảng các năm. Dùng lệnh cut để chia các khoảng thời gian, nhãn tương ứng với các khoảng lần lượt là “60_nam_truoc” (từ năm 1960 đến 1980), “40_nam_truoc” (từ năm 1980 đến 2000), “20_nam_truoc” (từ năm 2000 đến 2010), “10_nam_truoc” (từ năm 2010 đến 2020)
d <- d %>% mutate(classify = case_when(L < 3 | BHP < 100 ~ "Bad", L > 5 | BHP < 500 ~ "Normal", TRUE ~ "Good"))
  • Trong câu lệnh trên, ta muốn thêm một cột mới “classify” vào bộ dữ liệu “d”, phân loại các hàng dựa trên hai biến “L” và “BHP”. Các điều kiện phân loại được sử dụng trong case_when() như sau:

  • Nếu giá trị của “L” nhỏ hơn 3 hoặc giá trị của “BHP” nhỏ hơn 100, thì “classify” sẽ được gán giá trị “Bad”. Nếu giá trị của “L” nhỏ hơn 5 hoặc giá trị của “BHP” nhỏ hơn 500, thì “classify” sẽ được gán giá trị “Normal”. Trong trường hợp không thỏa điều kiện nào trong hai trường hợp trên, “classify” sẽ được gán giá trị “Good”. Kết quả là bộ dữ liệu “d” sẽ có một cột mới “classify” chứa thông tin về phân loại của mỗi hàng dựa trên điều kiện được xác định.

d <- d %>% mutate( classify = fct_relevel(classify, c("Bad", "Normal", "Good")))
  • Trong câu lệnh trên, ta muốn thay đổi thứ tự của các mức factor trong biến “classify” của bộ dữ liệu “d”. Cụ thể, ta đặt lại thứ tự của các mức factor trong biến “classify” theo thứ tự “Bad”, “Normal”, “Good”.

  • Kết quả là biến “classify” trong bộ dữ liệu “d” sẽ có thứ tự của các mức factor đã được đặt lại theo “Bad”, “Normal”, “Good”, và sẽ ảnh hưởng đến việc sắp xếp, hiển thị và phân loại trong các phép tính hoặc biểu đồ sau này.

3.3 Nhóm dữ liệu

d %>% group_by(Make) %>% tally()
## # A tibble: 71 × 2
##    Make             n
##    <chr>        <int>
##  1 Abarth         820
##  2 Aixam            2
##  3 Alfa Romeo    1698
##  4 Alpine           2
##  5 Aston Martin  1020
##  6 Audi          9146
##  7 Austin          20
##  8 BMW           7678
##  9 Bentley        790
## 10 Cadillac        26
## # ℹ 61 more rows
  • Nhóm dữ liệu “d” theo giá trị của biến “Make”.
  • Đếm số lượng dòng trong mỗi nhóm (tương ứng với số lượng xe từng hãng xe - “Make”).
  • Trả về một bộ dữ liệu mới chứa thông tin về số lượng xe từng hãng (Make) và số lượng xe của mỗi hãng.
  • Kết quả là bạn sẽ có một bộ dữ liệu mới với hai cột: “Make” chứa tên của các hãng xe và “n” chứa số lượng xe từng hãng.
d %>% group_by(Make, Model) %>% tally()
## # A tibble: 939 × 3
## # Groups:   Make [71]
##    Make   Model            n
##    <chr>  <chr>        <int>
##  1 Abarth 124 Spider      84
##  2 Abarth 500            246
##  3 Abarth 500C            46
##  4 Abarth 595            280
##  5 Abarth 595C           116
##  6 Abarth 695              8
##  7 Abarth 695C            10
##  8 Abarth Grande Punto    18
##  9 Abarth Punto Evo       12
## 10 Aixam  Coupe            2
## # ℹ 929 more rows
  • Câu lệnh trên sẽ thực hiện các bước sau:

  • Nhóm dữ liệu “d” theo giá trị của hai biến “Make” và “Model”. Đếm số lượng dòng trong mỗi nhóm (tương ứng với số lượng xe từng hãng xe và loại lốp xe mà hãng xe đó sử dụng - “Make” và “Model”).

  • Trả về một bộ dữ liệu mới chứa thông tin về số lượng xe từng hãng và từng loại lốp xe của mỗi hãng.

  • Kết quả là bạn sẽ có một bộ dữ liệu mới với ba cột: “Make” chứa tên của các hãng xe, “Model” chứa tên của từng loại lốp xe, và “n” chứa số lượng xe từng hãng và từng dòng xe.

3.4 Tính toán thống kê

summarisee <- function(data, var) {
  data %>% summarise( min = min({{var}}, na.rm = T), max = max({{var}}, na.rm=T), mean = mean({{var}}, na.rm=T), sum = sum({{var}},na.rm=T),median = median({{var}},na.rm=T), numeric = is.numeric({{var}}), vector= is.vector({{var}}), sd = sd({{var}}, na.rm=T),var = var({{var}}, na.rm=T), quantile = quantile({{var}}, na.rm = T), n= n())
}
  • Dưới đây là giải thích về các phần của hàm summarisee mới tạo:

  • summarisee <- function(data, var) { … }: Đây là khai báo của hàm summarisee với hai đối số là data và var. Đối số data là bộ dữ liệu (data frame) mà bạn muốn tổng hợp thông tin thống kê. Đối số var là tên của biến (cột) trong bộ dữ liệu mà bạn muốn tính toán thông tin thống kê.

  • summarise(…): Đây là một hàm trong package dplyr dùng để tổng hợp thông tin thống kê của bộ dữ liệu. Trong đoạn mã, chúng ta sử dụng hàm summarise để tính các giá trị tối thiểu, tối đa, trung bình, tổng, trung vị, số lượng phần tử, độ lệch chuẩn, phương sai và phân vị (quantile) của biến var trong bộ dữ liệu.

  • Các giá trị trong hàm summarise(…) được tính toán bằng cách sử dụng các hàm thống kê của R như min(), max(), mean(), sum(), median(), sd(), var(), quantile(), và n(). Thêm vào đó, ta sử dụng is.numeric() và is.vector() để kiểm tra xem biến var có phải là dạng số (numeric) và là một vector hay không.

  • Mỗi giá trị tính toán trong hàm summarise(…) được đặt tên thông qua các cặp tên = giá trị.

  • Cuối cùng, hàm summarisee trả về một bộ dữ liệu mới chứa thông tin thống kê của biến var trong bộ dữ liệu data.

summarisee(d, d$Price)
## Warning: Returning more (or less) than 1 row per `summarise()` group was deprecated in
## dplyr 1.1.0.
## ℹ Please use `reframe()` instead.
## ℹ When switching from `summarise()` to `reframe()`, remember that `reframe()`
##   always returns an ungrouped data frame and adjust accordingly.
## Call `lifecycle::last_lifecycle_warnings()` to see where this warning was
## generated.
## # A tibble: 5 × 11
##     min    max   mean    sum median numeric vector     sd    var quantile      n
##   <dbl>  <dbl>  <dbl>  <dbl>  <dbl> <lgl>   <lgl>   <dbl>  <dbl>    <dbl>  <int>
## 1   100 1.23e6 16698. 1.70e9   8911 TRUE    TRUE   32290. 1.04e9      100 101992
## 2   100 1.23e6 16698. 1.70e9   8911 TRUE    TRUE   32290. 1.04e9     3990 101992
## 3   100 1.23e6 16698. 1.70e9   8911 TRUE    TRUE   32290. 1.04e9     8911 101992
## 4   100 1.23e6 16698. 1.70e9   8911 TRUE    TRUE   32290. 1.04e9    17200 101992
## 5   100 1.23e6 16698. 1.70e9   8911 TRUE    TRUE   32290. 1.04e9  1234566 101992
  • Gọi hàm summarisee(d, d$Price), sử dụng hàm summarisee để tính toán thông tin thống kê của biến “Price” trong bộ dữ liệu “d”. Sau khi gọi hàm này, sẽ nhận được một bộ dữ liệu mới chứa các thông tin thống kê như tối thiểu, tối đa, trung bình, tổng, trung vị, số lượng phần tử, độ lệch chuẩn, phương sai, phân vị và số lượng phần tử của biến “Price” trong bộ dữ liệu “d”.

3.5 Cắt hàng theo nhóm

groupby <- function(a,b,c,d) {
  a %>% group_by({{b}}) %>% arrange({{b}}, {{c}}) %>% slice_head(n =5) %>% arrange({{b}}) %>% select({{b}},{{c}},{{d}})
}

Kết quả là hàm groupby sẽ thực hiện các bước sau:

  • Nhóm các dòng của bộ dữ liệu a theo giá trị của biến b.
  • Sắp xếp các dòng theo giá trị của biến b và sau đó theo giá trị của biến c.
  • Giữ lại chỉ 5 dòng đầu tiên của mỗi nhóm sau khi đã nhóm và sắp xếp.
  • Tiếp tục sắp xếp bộ dữ liệu theo giá trị của biến b, để đảm bảo dữ liệu vẫn được sắp xếp sau khi giữ lại chỉ 5 dòng đầu tiên trong mỗi nhóm.
  • Chọn và giữ lại các biến b, c, và d trong bộ dữ liệu kết quả.
groupby(d,Make,Model,Price)
## # A tibble: 341 × 3
## # Groups:   Make [71]
##    Make       Model      Price
##    <chr>      <chr>      <dbl>
##  1 Abarth     124 Spider 18799
##  2 Abarth     124 Spider 18980
##  3 Abarth     124 Spider 18999
##  4 Abarth     124 Spider 19600
##  5 Abarth     124 Spider 21250
##  6 Aixam      Coupe       5950
##  7 Aixam      Coupe       5950
##  8 Alfa Romeo 146         2950
##  9 Alfa Romeo 146         2950
## 10 Alfa Romeo 147          600
## # ℹ 331 more rows
  • Nhóm các dòng của bộ dữ liệu “d” theo giá trị của biến “Make”.
  • Sắp xếp các dòng theo giá trị của biến “Make” và sau đó theo giá trị của biến “Model”.
  • Giữ lại chỉ 5 dòng đầu tiên của mỗi nhóm sau khi đã nhóm và sắp xếp.
  • Tiếp tục sắp xếp bộ dữ liệu theo giá trị của biến “Make”, để đảm bảo dữ liệu vẫn được sắp xếp sau khi giữ lại chỉ 5 dòng đầu tiên trong mỗi nhóm.
  • Chọn và giữ lại các cột “Make”, “Model”, và “Price” trong bộ dữ liệu kết quả.
groupby(d,Make,Year,Fuel)
## # A tibble: 341 × 3
## # Groups:   Make [71]
##    Make        Year Fuel  
##    <chr>      <dbl> <chr> 
##  1 Abarth      2008 Petrol
##  2 Abarth      2008 Petrol
##  3 Abarth      2008 Petrol
##  4 Abarth      2008 Petrol
##  5 Abarth      2009 Petrol
##  6 Aixam       2014 Diesel
##  7 Aixam       2014 Diesel
##  8 Alfa Romeo  1990 Petrol
##  9 Alfa Romeo  1990 Petrol
## 10 Alfa Romeo  1991 Petrol
## # ℹ 331 more rows
  • Nhóm các dòng của bộ dữ liệu “d” theo giá trị của biến “Make”.
  • Sắp xếp các dòng theo giá trị của biến “Make” và sau đó theo giá trị của biến “Year”.
  • Giữ lại chỉ 5 dòng đầu tiên của mỗi nhóm sau khi đã nhóm và sắp xếp.
  • Tiếp tục sắp xếp bộ dữ liệu theo giá trị của biến “Make”, để đảm bảo dữ liệu vẫn được sắp xếp sau khi giữ lại chỉ 5 dòng đầu tiên trong mỗi nhóm.
  • Chọn và giữ lại các cột “Make”, “Year”, và “Fuel” trong bộ dữ liệu kết quả.
  • Kết quả của phép nhóm và sắp xếp này sẽ là một bộ dữ liệu mới chứa 5 dòng đầu tiên trong mỗi nhóm của các giá trị “Make” và “Year”, và chỉ bao gồm các cột “Make”, “Year”, và “Fuel”.

3.6 Đếm dữ liệu

d %>% count(Fuel, Trans)
## # A tibble: 12 × 3
##    Fuel                             Trans         n
##    <chr>                            <chr>     <int>
##  1 Diesel                           Automatic 18913
##  2 Diesel                           Manual    28291
##  3 Hybrid – Diesel/Electric         Automatic    53
##  4 Hybrid – Diesel/Electric         Manual        2
##  5 Hybrid – Diesel/Electric Plug-in Automatic     5
##  6 Hybrid – Petrol/Electric         Automatic  1862
##  7 Hybrid – Petrol/Electric         Manual      147
##  8 Hybrid – Petrol/Electric Plug-in Automatic   419
##  9 Petrol                           Automatic 17715
## 10 Petrol                           Manual    34582
## 11 Petrol Ethanol                   Automatic     2
## 12 Petrol Ethanol                   Manual        1
  • Kết quả là bạn sẽ có một bộ dữ liệu mới chứa thông tin về số lượng dòng trong bộ dữ liệu “d” được nhóm theo các giá trị của hai biến “Fuel” và “Trans”. Các cột trong bộ dữ liệu mới sẽ là “Fuel”, “Trans”, và “n”, trong đó “Fuel” chứa các giá trị của biến “Fuel”, “Trans” chứa các giá trị của biến “Trans”, và “n” chứa số lượng dòng tương ứng với mỗi cặp giá trị “Fuel” và “Trans”.
d %>% count(Make) %>% mutate(percent = scales::percent(n/sum(n)))
## # A tibble: 71 × 3
##    Make             n percent 
##    <chr>        <int> <chr>   
##  1 Abarth         820 0.80398%
##  2 Aixam            2 0.00196%
##  3 Alfa Romeo    1698 1.66484%
##  4 Alpine           2 0.00196%
##  5 Aston Martin  1020 1.00008%
##  6 Audi          9146 8.96737%
##  7 Austin          20 0.01961%
##  8 BMW           7678 7.52804%
##  9 Bentley        790 0.77457%
## 10 Cadillac        26 0.02549%
## # ℹ 61 more rows
  • Kết quả thể hiện thông tin về số lượng dòng của mỗi nhóm “Make” và phần trăm tương ứng của số lượng dòng đó trong toàn bộ bộ dữ liệu. Cột “Make” chứa các giá trị của biến “Make”, cột “n” chứa số lượng dòng tương ứng với mỗi giá trị “Make”, và cột “percent” chứa phần trăm tương ứng của số lượng dòng theo tổng số dòng trong bộ dữ liệu.
d %>% group_by(Make) %>% count(Model) %>% mutate(percent = scales::percent(n/sum(n)))
## # A tibble: 939 × 4
## # Groups:   Make [71]
##    Make   Model            n percent
##    <chr>  <chr>        <int> <chr>  
##  1 Abarth 124 Spider      84 10.24% 
##  2 Abarth 500            246 30.00% 
##  3 Abarth 500C            46 5.61%  
##  4 Abarth 595            280 34.15% 
##  5 Abarth 595C           116 14.15% 
##  6 Abarth 695              8 0.98%  
##  7 Abarth 695C            10 1.22%  
##  8 Abarth Grande Punto    18 2.20%  
##  9 Abarth Punto Evo       12 1.46%  
## 10 Aixam  Coupe            2 100%   
## # ℹ 929 more rows
  • Kết quả là một bộ dữ liệu mới chứa thông tin về số lượng dòng của mỗi nhóm “Make - Model” và phần trăm tương ứng của số lượng dòng đó trong toàn bộ bộ dữ liệu. Các cột trong bộ dữ liệu mới sẽ là “Make”, “Model”, “n” (số lượng dòng), và “percent” (phần trăm số lượng dòng).

4 Data visualization (Trực quan hoá dữ liệu)

map <- function(a,b,c,d) {
  a %>% filter({{c}}>100) %>% ggplot(map = aes(x = {{b}}, y ={{c}}, color = {{d}})) + geom_point() + geom_smooth(formula = y~ x, method = "lm", color = "black")
}

Giải thích function trên:

  • a: Đây là tên của bộ dữ liệu

  • b, c, d: Đây là các biến (cột) trong bộ dữ liệu “a” mà bạn muốn sử dụng trong biểu đồ. Biến “b” sẽ được sử dụng trên trục x, biến “c” sẽ được sử dụng trên trục y, và biến “d” sẽ xác định màu sắc của các điểm trên biểu đồ.

  • filter({{c}}>100): Đây là một hàm trong package dplyr dùng để lọc (filter) các dòng của bộ dữ liệu dựa trên điều kiện {{c}}>100. Điều này có nghĩa là chỉ giữ lại các dòng có giá trị của biến “c” lớn hơn 100.

  • ggplot(...): Đây là hàm trong package ggplot2 để bắt đầu vẽ biểu đồ. Hàm này yêu cầu bạn cung cấp bộ dữ liệu và các mappings (mapping aesthetics) để xác định các thành phần trong biểu đồ.

  • aes(x = {{b}}, y ={{c}}, color = {{d}}): Đây là một phần của hàm ggplot(), xác định các mappings aesthetics. Trong đoạn mã, biến “b” sẽ được sử dụng làm trục x của biểu đồ, biến “c” làm trục y, và biến “d” làm màu sắc của các điểm trên biểu đồ.

  • geom_point(): Đây là một hàm trong package ggplot2 để vẽ điểm trên biểu đồ. Nó sẽ thêm các điểm dữ liệu lên biểu đồ dựa trên các mappings aesthetics đã được xác định ở trên.

  • geom_smooth(formula = y~ x, method = "lm", color = "black"): Đây là một hàm trong package ggplot2 để vẽ đường phân loại (trendline) trên biểu đồ. Trong đoạn mã, chúng ta sử dụng hàm geom_smooth() để thêm một đường phân loại dựa trên mô hình tuyến tính (method = “lm”) vào biểu đồ. Đường phân loại này sẽ thể hiện xu hướng tổng quát của dữ liệu. Tham số formula = y ~ x xác định mô hình tuyến tính dựa trên trục x và trục y của biểu đồ. Tham số color = "black" xác định màu đường phân loại là đen.

  • Kết quả là khi bạn gọi hàm map(a, b, c, d), nó sẽ thực hiện lọc các dòng của bộ dữ liệu “a” sao cho giá trị của biến “c” lớn hơn 100, sau đó vẽ biểu đồ sử dụng gói ggplot2 trên bộ dữ liệu đã lọc. Biểu đồ sẽ có các điểm dữ liệu theo mappings aesthetics xác định bởi các biến “b”, “c”, và “d”, và điểm dữ liệu sẽ được nối bằng đường phân loại dựa trên mô hình tuyến tính, đại diện bởi đường màu đen.

map(d,Price,BHP,Trans)

  • khi gọi hàm map(d, Price, BHP, Trans), nó sẽ thực hiện lọc các dòng của bộ dữ liệu “d” sao cho giá trị của biến “BHP” lớn hơn 100, sau đó vẽ biểu đồ trên bộ dữ liệu đã lọc. Biểu đồ sẽ có các điểm dữ liệu xác định bởi biến “Price” và “BHP”, và điểm dữ liệu sẽ được nối bằng đường phân loại dựa trên mô hình tuyến tính, đại diện bởi đường màu đen. Kết quả cho ta thấy nếu giá càng tăng cao thì sẽ mua được chiếc xe có công suất cao hơn
map(d,L,BHP,classify)

  • Câu lệnh trên thực hiện lọc các dòng của bộ dữ liệu “d” sao cho giá trị của biến “BHP” lớn hơn 100, sau đó vẽ biểu đồ trên bộ dữ liệu đã lọc. Biểu đồ sẽ có các điểm dữ liệu xác định bởi biến “L” và “BHP”, và điểm dữ liệu sẽ được nối bằng đường phân loại dựa trên mô hình tuyến tính, đại diện bởi đường màu đen. Kết quả trên cho ta thấy dung tích nhiên liệu càng cao thì công suất của chiếc xe đó càng lớn.