# Clear Workspace
rm(list = ls())

# Load libraries
library(dplyr)
library(readr)
library(stringr)
library(tidyr)
library(ggplot2)

# Working directory path 
data_path <- "D:\\DATA_SCIENCE\\R_COURSE_CASED\\Lecture_3\\multiple_choice_responses_aDung.csv"

# Load data 

df_raw <- read_csv(data_path, skip = 1)

Assignment 1

Q1.

Tại sao trong đoạn mã đọc dữ liệu ở trên lại sử dụng skip = 1 để loại bỏ dòng 1 khi đọc vào dữ liệu?

Answer: Dòng 1 chứa số thứ tự câu hỏi. Có thể sử dụng dòng này để làm tên biến (tương ứng với từng cột dữ liệu) nhưng việc đặt tên như vậy không giúp ích cho việc phân tích dữ liệu vì cách đánh số không chứa thông tin gì về cột dữ liệu. Trên thực tế ta sử dụng nội dung câu hỏi (chứa ở dòng số 2) làm tên cột biến.

Q2.

Tên các cột biến có sử dụng dấu cách (space). Hãy thay thế tất cả các dấu cách bằng dấu gạch dưới (underscore).

# Thay the ki tu cho vector chua ten cac cot bien 

df_raw  %>% names() %>% str_replace_all(" ","_") -> new_names

# Su dung ham names() de gan vector new_names cho dataframe

names(df_raw) <- new_names

Q3.

Tách ra data frame chỉ gồm hai cột biến là What_is_your_gender?_-_Selected_Choice và In_which_country_do_you_currently_reside? rồi đổi tên cho chúng lần lượt thành gender và nation

# Lua chon cot bien thu 3 va thu 5 cho 2 bien can tach sau do dung ham rename()
# de doi ten

df_raw  %>%  
  select(3,5)  %>% 
  rename(gender = `What_is_your_gender?_-_Selected_Choice`, 
         nation = `In_which_country_do_you_currently_reside?`) -> df_country_gender

Q4.

Tính toán tỉ lệ nữ làm nghề Data Science cho tất cả các quốc gia trong mẫu khảo sát

# Tinh so luong respondents cho tung quoc gia, luu thanh df_country 
df_country_gender  %>% group_by(nation, gender)  %>% count() -> df_country

# Chuyen df_country sang wide form 
df_country  %>% pivot_wider(names_from = gender, values_from = n) -> df_country_wide

# Tinh ti le nu cho tung quoc gia, lam tron 2 chu so sau dau phay va sap xep giam dan. 
# Ghi chu: Bo qua cac quan sat khong ro gioi tinh (Prefer Not to say/Prefer to self-describe)

df_country_wide  %>% 
  mutate(female_rate = Female/(Female + Male))  %>% 
  arrange(-female_rate) -> df_country_wide

df_country_wide
## # A tibble: 59 x 6
## # Groups:   nation [59]
##    nation         Female  Male `Prefer not to s~ `Prefer to self-de~ female_rate
##    <chr>           <int> <int>             <int>               <int>       <dbl>
##  1 Tunisia            33    35                NA                  NA       0.485
##  2 Philippines        19    41                 5                  NA       0.317
##  3 Iran, Islamic~     28    67                 1                  NA       0.295
##  4 Malaysia           22    53                 5                  NA       0.293
##  5 Kenya              29    85                NA                  NA       0.254
##  6 Ireland            22    65                 2                  NA       0.253
##  7 Turkey             66   218                 3                   1       0.232
##  8 Indonesia          38   127                 1                   1       0.230
##  9 Canada             99   334                13                   4       0.229
## 10 Thailand           15    51                 1                  NA       0.227
## # ... with 49 more rows

Q5.

Lấy ra danh sách 20 quốc gia bao gồm Việt Nam và 19 quốc gia có tỉ lệ nữ làm Data Science lớn nhất (top 19)

# I'm not really happy doing this way but I have yet came up with an alternative 
# The 19th country has female rate = 0.1936

df_country_wide  %>% 
  filter(female_rate >= 0.1936 | nation == "Viet Nam") -> df_country_20

Q6.

Sử dụng dữ liệu có được ở Q5 hãy tạo ra (hoặc mô phỏng) lại biểu đồ Bar ở nhằm biểu diễn tỉ lệ Nữ làm Data Science cho 20 quốc gia đã được chọn như sau

# Doi ten cho mot so quoc gia vi qua dai
# Sap xep theo chieu ti le nu giam dan 

df_country_20  %>% 
  mutate(nation = case_when(str_detect(nation, "United Kingdom") ~ "United Kingdom",
                            str_detect(nation, "Iran") ~ "Iran",
                            str_detect(nation, "America") ~ "USA",
                            TRUE ~ nation))  %>% 
  #mutate(male_rate = 1 - female_rate)  %>% 
  arrange(female_rate) -> df_sorted

# ????
df_sorted  %>% mutate(nation = factor(nation, levels = df_sorted$nation)) -> df_sorted

# Chuan bi du lieu cho ve bieu do
# Tao label cho female_rate

df_sorted  %>% 
  select("nation", "Female", "Male", "female_rate") %>%
  pivot_longer(cols = c("Female", "Male"), names_to = "gender")  %>% 
  mutate(label = as.character(round(female_rate,3)*100))   %>% 
  mutate(label = case_when(str_detect(label,"\\.") ~ str_c(label,"%"),
                                              TRUE ~ str_c(label,".0%"))) -> df_long

# Ve bieu do 

library(viridis)

df_long  %>% 
  ggplot(aes(x = value, y = nation, fill = gender)) +
  geom_col(position = "fill") +
  theme_minimal() +
  theme(legend.position = "top", legend.title = element_blank()) + 
  theme(axis.title = element_blank()) +
  theme(axis.ticks.y = element_blank()) +
  theme(panel.grid = element_blank()) +
  scale_x_continuous(labels = paste0(seq(0, 100, 25), "%"), expand = c(0, 0)) +
  geom_text(aes(x = 1, y = nation, label = label), color = "white", hjust = 1.2, size = 3) + 
  labs(title = "Fact 1: Women in Machine Learning and Data Science Community",
       x = NULL, y = NULL,
       caption = "Source: 2019 Kaggle ML & DS Survey")

Bài chữa 1

# Clear Workspace
rm(list = ls())

# Load libraries
library(dplyr)
library(readr)
library(stringr)
library(tidyr)
library(ggplot2)

# Working directory path 
data_path <- "D:\\DATA_SCIENCE\\R_COURSE_CASED\\Lecture_3\\multiple_choice_responses_aDung.csv"

# Load data 

df_raw <- read_csv(data_path, skip = 1)

# Doi ten 

df_raw  %>% names() %>% str_replace_all(" ","_") -> new_names

names(df_raw) <- new_names

df_raw  %>%  
  select(`What_is_your_gender?_-_Selected_Choice`, 
         `In_which_country_do_you_currently_reside?`) -> df_mini


names(df_mini) <- c("gender", "country")

some_genders <- c("Male", "Female")

df_mini  %>% 
  filter(gender  %in% some_genders) -> df_mini

library(tidyr)

df_mini  %>% 
  group_by(gender, country)  %>% 
  count()  %>% 
  pivot_wider(names_from = "gender", values_from = "n")  %>% 
  mutate(rate = Female/(Female + Male)) -> df_rate

# Loc top 19 va Viet Nam

# Cach 1 
df_rate  %>% 
  ungroup()  %>% 
  top_n(n = 19, wt = rate) -> df_top19

# Cach 2 
df_rate  %>% 
  ungroup()  %>% 
  arrange(-rate)  %>% 
  slice(1:19) -> df_top19_2

# Vi sao can dung ungroup 
# df_rate chiu anh huong boi group_by

str(df_rate)
## tibble [59 x 4] (S3: grouped_df/tbl_df/tbl/data.frame)
##  $ country: chr [1:59] "Algeria" "Argentina" "Australia" "Austria" ...
##  $ Female : int [1:59] 12 13 44 5 7 12 5 79 99 10 ...
##  $ Male   : int [1:59] 46 108 218 47 127 55 62 643 334 81 ...
##  $ rate   : num [1:59] 0.2069 0.1074 0.1679 0.0962 0.0522 ...
##  - attr(*, "groups")= tibble [59 x 2] (S3: tbl_df/tbl/data.frame)
##   ..$ country: chr [1:59] "Algeria" "Argentina" "Australia" "Austria" ...
##   ..$ .rows  : list<int> [1:59] 
##   .. ..$ : int 1
##   .. ..$ : int 2
##   .. ..$ : int 3
##   .. ..$ : int 4
##   .. ..$ : int 5
##   .. ..$ : int 6
##   .. ..$ : int 7
##   .. ..$ : int 8
##   .. ..$ : int 9
##   .. ..$ : int 10
##   .. ..$ : int 11
##   .. ..$ : int 12
##   .. ..$ : int 13
##   .. ..$ : int 14
##   .. ..$ : int 15
##   .. ..$ : int 16
##   .. ..$ : int 17
##   .. ..$ : int 18
##   .. ..$ : int 19
##   .. ..$ : int 20
##   .. ..$ : int 21
##   .. ..$ : int 22
##   .. ..$ : int 23
##   .. ..$ : int 24
##   .. ..$ : int 25
##   .. ..$ : int 26
##   .. ..$ : int 27
##   .. ..$ : int 28
##   .. ..$ : int 29
##   .. ..$ : int 30
##   .. ..$ : int 31
##   .. ..$ : int 32
##   .. ..$ : int 33
##   .. ..$ : int 34
##   .. ..$ : int 35
##   .. ..$ : int 36
##   .. ..$ : int 37
##   .. ..$ : int 38
##   .. ..$ : int 39
##   .. ..$ : int 40
##   .. ..$ : int 41
##   .. ..$ : int 42
##   .. ..$ : int 43
##   .. ..$ : int 44
##   .. ..$ : int 45
##   .. ..$ : int 46
##   .. ..$ : int 47
##   .. ..$ : int 48
##   .. ..$ : int 49
##   .. ..$ : int 50
##   .. ..$ : int 51
##   .. ..$ : int 52
##   .. ..$ : int 53
##   .. ..$ : int 54
##   .. ..$ : int 55
##   .. ..$ : int 56
##   .. ..$ : int 57
##   .. ..$ : int 58
##   .. ..$ : int 59
##   .. ..@ ptype: int(0) 
##   ..- attr(*, ".drop")= logi TRUE
str(df_mini)
## tibble [19,350 x 2] (S3: tbl_df/tbl/data.frame)
##  $ gender : chr [1:19350] "Male" "Male" "Female" "Male" ...
##  $ country: chr [1:19350] "France" "India" "Germany" "Australia" ...
bind_rows(df_top19_2, df_rate  %>% ungroup()  %>% filter(country == "Viet Nam")) -> df_total

df_total  %>% 
  pivot_longer(cols = c("Female", "Male"), names_to = "gender", values_to = "value") -> df_plot


df_plot  %>% 
  mutate(country = case_when(str_detect(country, "America") ~ "United States",
                             str_detect(country, "Kingdom") ~ "United Kingdom", 
                             str_detect(country, "Iran") ~ "Iran",
                             TRUE ~ country)) -> df_plot

df_plot  %>% 
  filter(duplicated(country))  %>% 
  arrange(rate) -> df_arranged

df_plot  %>% 
  mutate(country = factor(country, levels = df_arranged$country))  %>%    
  #df_arranged$country[20:1] neu di cung arrange(-rate)
  ggplot(aes(x = country, y = value, fill = gender)) +
  geom_col(position = "fill") +
  coord_flip() + 
  theme(axis.title = element_blank(),
        axis.ticks = element_blank()) 

Assignment 2

# Clear Workspace
rm(list = ls())

# Load required library
library(dplyr)
library(rvest)
library(stringr)
library(stringi)
library(ggplot2)

Q1.

Object có tên all_links_communes_level được tạo ra đoạn R Codes dưới đây:

all_links <- "https://www.citypopulation.de/Vietnam.html"

pg <- read_html(all_links)

m <- html_nodes(pg, "a")

k <- html_attr(m, "href")

all_links_communes_level <-  str_c("https://www.citypopulation.de/en/vietnam/", k[-c(1:6)])

Thuộc dạng dữ liệu gì? Mỗi phần tử của all_links_communes_level là link dẫn đến thông tin gì?

  • Dữ liệu kiểu character/text. Cụ thể là mỗi phần tử là text chứa đường link dẫn đến thông tin về hành chính của từng tỉnh/thành phố ở Việt Nam. Thông tin về mỗi tỉnh được thể hiện qua

  • Bản đồ hành chính của tỉnh + mật độ dân số của từng huyện khi trỏ chuột đến vị trí tương ứng trên bản đồ

  • Bảng số liệu về dân số của từng tỉnh

  • Ngoài ra còn rất nhiều thông tin khác khi click chuột vào các tab.

Q2.

Xét đoạn mã dưới đây:

specific_link <- all_links_communes_level[1]

specific_link
## [1] "https://www.citypopulation.de/en/vietnam/cantho/admin/"
specific_link %>% 
  read_html() %>% 
  html_nodes(xpath = '//*[@id="tl"]') %>% 
  html_table(fill = TRUE) %>% 
  .[[1]] -> df

head(df)
##                   Name         Status PopulationCensus2009-04-01         
## 1     Bình Th<U+1EE7>y Urban District                    113,565 <U+2192>
## 2       An Th<U+1EDB>i           Ward                     18,499 <U+2192>
## 3     Bình Th<U+1EE7>y           Ward                     18,307 <U+2192>
## 4 Bùi H<U+1EEF>u Nghia           Ward                     11,745 <U+2192>
## 5             Long Hòa           Ward                     16,450 <U+2192>
## 6    Long Tuy<U+1EC1>n           Ward                     15,232 <U+2192>

Trong đoạn mã trên nếu thay all_links_communes_level[1] thành all_links_communes_level[2] thì hệ quả sẽ là gì? Có thể thay thành all_links_communes_level[100] được không?

  • Số [1] chỉ định phần tử đầu tiên của vector all_link_communes_level, tương ứng với “cantho/admin/”. Lúc này specific_link chứa đường link dẫn đến trang thông tin của tỉnh Cần Thơ.

  • Khi thay thành số [2] thì specific_link được gán với đường link dẫn đến trang thông tin của tỉnh thứ 2 trong danh sách là Đà Nẵng.

  • Không thể thay thành …[100] vì all_links_communes_level chỉ có 63 phần tử, tương ứng với 63 tỉnh/thành phố. (Nếu để 100 thì specific_link sẽ báo giá trị NA).

Q3.

Từ phân tích và nhận xét rút ra ở Q2 hãy viết một hàm mà nhận input là địa chỉ link của HTML và trả về kết quả (output) là một Data Frame chứa thông tin về dân số theo Huyện và Xã tương ứng với địa chỉ link của HTML.

data_extract <- function(html_link) {
  html_link %>% 
      read_html() %>% 
      html_nodes(xpath = '//*[@id="tl"]') %>% 
      html_table(fill = TRUE) %>% 
      .[[1]]  %>% 
      select(1:3) -> output
  
  return(output)
}

Q4.

Từ dữ liệu đã có ở Q3 hãy vẽ Choropleth Map minh họa mật độ dân số của Việt Nam theo cấp: (a) Tình, (b) Huyện. Giải thuyết rằng những số liệu về dân số thu được (kể cả cấp Huyện lẫn Xã) chính là mật độ dân số

Bước 1. Load dữ liệu dân số

# Su dung for loop thay vi ham lapply

m <- length(all_links_communes_level)

empty_df <- data.frame()


for (k in 1:m) {
  
  my_df <- data_extract(all_links_communes_level[k])
  
  empty_df <- bind_rows(empty_df, my_df)
}



# Su dung ham extract du lieu de lay ve du lieu cho cac tinh
lapply(all_links_communes_level, data_extract) -> all_provinces 

# Noi cac bang du lieu cua tung tinh tao thanh bo du lieu ca quoc gia
do.call("bind_rows", all_provinces) -> vn_pop_data

# Doi ten bien, doi font chu & xu ly du lieu dan so 

vn_pop_data  %>% 
  rename(name = Name, status = Status, pop = `PopulationCensus2009-04-01`)  %>% 
  mutate(name = stri_trans_general(name, "Latin-ASCII"))  %>% 
  mutate(pop = str_replace_all(pop,",",""))  %>% 
  mutate(pop = as.numeric(pop))  %>% 
  mutate(pop = pop/1000) -> vn_pop_data

# Filter du lieu cap tinh va cap huyen 

vn_pop_data  %>% filter(status  %in% c("Municipality", "Province")) -> province_pop_data

vn_pop_data  %>% filter(str_detect(status, "District")) -> district_pop_data

Bước 2. Load dữ liệu bản đồ

# Du lieu ban do cap tinh

province_map_data <- raster::getData(name = "GADM", country = "vietnam", level = 1)  %>% 
                             fortify(region = "NAME_1")  %>% 
                             mutate(name = stri_trans_general(id, "Latin-ASCII")) 

# Du lieu ban do cap huyen

district_map_data <- raster::getData(name = "GADM", country = "vietnam", level = 2)  %>% 
                             fortify(region = "NAME_2")  %>% 
                             mutate(name = stri_trans_general(id, "Latin-ASCII"))

Bước 3. Nối dữ liệu bản đồ với dữ liệu dân số

# Mot so tinh co ten khong khop nhau trong 2 bo du lieu

base::setdiff(province_pop_data$name, province_map_data$name  %>% unique()) -> prov_diff

province_pop_data  %>% 
  mutate(name = case_when(name == prov_diff[1] ~ "Ha Noi",
                          name == prov_diff[2] ~ "Ho Chi Minh",
                          name == prov_diff[3] ~ "Thua Thien Hue",
                                          TRUE ~ name)) -> province_pop_data
  
# 19 huyen co ten khong khop nhau trong 2 bo du lieu. Hien tai ta bo qua van de nay. 

# Noi du lieu ban do voi du lieu dan so theo ten tinh/huyen

full_join(province_map_data, province_pop_data, by = "name") -> df_provinces

full_join(district_map_data, district_pop_data, by = "name") -> df_districts

Bước 4. Vẽ

4.1 Biểu đồ mật độ dân số theo cấp tỉnh

library(viridis)

ggplot() +
  geom_polygon(data = df_provinces, aes(x = long, y = lat, group = group, fill = pop), color = "grey80") + 
  theme_minimal() +
  theme(axis.title = element_blank(), 
        axis.ticks = element_blank(), 
        axis.text = element_blank(),
        panel.grid = element_blank()) + 
  labs(title = "Figure 1: Population Density in Vietnam By Provincial Level",
       subtitle = "(per thousand people)",
       caption = "Source: https://www.citypopulation.de/en/vietnam & GADM") + 
  scale_fill_viridis(direction = -1, 
                     option = "viridis",
                     name = "Density")

4.2 Biểu đồ mật độ dân số theo cấp huyện

ggplot() +
  geom_polygon(data = df_districts, aes(x = long, y = lat, group = group, fill = pop), color = "grey80") + 
  theme_minimal() +
  theme(axis.title = element_blank(), 
        axis.ticks = element_blank(), 
        axis.text = element_blank(),
        panel.grid = element_blank()) + 
  labs(title = "Figure 2: Population Density in Vietnam By District Level",
       subtitle = "(per thousand people)",
       caption = "Source: https://www.citypopulation.de/en/vietnam & GADM") + 
  scale_fill_viridis(direction = -1, 
                     option = "magma",
                     name = "Density")