1 Các thư viện sử dụng

  • stringr để xử lý chữ
  • readxl để nạp dữ liệu từ file excel
  • writexl để ghi kết quả ra file excel
  • stringi để bỏ dấu tiếng Việt
library(stringr)
library(dplyr)
## 
## Attaching package: 'dplyr'
## The following objects are masked from 'package:stats':
## 
##     filter, lag
## The following objects are masked from 'package:base':
## 
##     intersect, setdiff, setequal, union
library(readxl)
library(stringi)
library(writexl)

2 Dữ liệu

Province_city_mining.xlsx - là dữ liệu cần xử lý. Cột province_city được bỏ dấu tiếng Việt.

raw_df <- read_excel("Province_city_mining.xlsx") %>% 
  mutate(province_city = stri_trans_general(province_city, 
                                            "Latin-ASCII"))

raw_df %>% head(4)
## # A tibble: 4 x 3
##   recid cus_name                  province_city
##   <chr> <chr>                     <chr>        
## 1 1     KHACH HANG VANG LAI       Ha Noi       
## 2 10    DINH CHE TAI CHINH        Ha Noi       
## 3 100   VPBANK                    <NA>         
## 4 1000  CONG TY TNHH SAO BAC VIET <NA>

Dia-Gioi-Hanh-Chinh-VietNam.xls Bao gồm các thông tin về danh sách 63 tình thành phố trực thuộc trung ương và các thành phố/quận/huyện trực thuộc chúng. Dữ liệu này được sử dụng để đoán nhận xem thông tin ở province_city của Province_city_mining.xlsx là tỉnh thành phố trực thuộc trung ương nào. Các cột tên đều được bỏ dấu tiếng Việt

p_data <- read_excel("Dia-Gioi-Hanh-Chinh-VietNam.xls", 
                     sheet = "Province") %>% 
  mutate(pname = stri_trans_general(pname, 
                                    "Latin-ASCII"))
d_data <- read_excel("Dia-Gioi-Hanh-Chinh-VietNam.xls", 
                     sheet = "District") %>% 
  mutate(dname = stri_trans_general(dname, 
                                    "Latin-ASCII"))

p_data %>% head(3)
## # A tibble: 3 x 2
##   pcode pname   
##   <chr> <chr>   
## 1 01    Ha Noi  
## 2 02    Ha Giang
## 3 04    Cao Bang
d_data %>% head(3)
## # A tibble: 3 x 2
##   dname     pcode
##   <chr>     <chr>
## 1 Ba Dinh   01   
## 2 Hoan Kiem 01   
## 3 Tay Ho    01

3 Tiêu chuẩn hóa tên tỉnh thành phố

Hàm standardize_pc biến đổi tên: chuyển thành chữ thường, bỏ số/dấu câu/dấu cách, loại bỏ các tiền tố tp, thanhpho, tinh. Điều này cho phép sau khi biến đổi thì các tên giống nhau sẽ trùng nhau dù cách viết khác nhau.

standardize_pc <- function(pc) {
  pc %>% 
    tolower() %>%
    str_replace_all("[[[:punct:]]\\d[[:space:]]]", 
                    "") %>% 
    str_replace_all("^(tp|tinh|thanhpho)", 
                    "")
}

4 Tạo Regular Expression tìm kiếm

Tên quận huyện được gắn với tên tỉnh thành tương ứng bằng left_join

d_map <- left_join(d_data, 
                   p_data) %>% 
  select(dname, 
         pname)
## Joining, by = "pcode"
d_map %>% head(3)
## # A tibble: 3 x 2
##   dname     pname 
##   <chr>     <chr> 
## 1 Ba Dinh   Ha Noi
## 2 Hoan Kiem Ha Noi
## 3 Tay Ho    Ha Noi

Tên tỉnh thành cũng được gắn với chính nó để khi nối với d_map tạo ra danh sách đối chiếu tên bất kỳ và tên tỉnh thành.

p_map <- p_data %>% 
  mutate(dname = pname) %>% 
  select(dname, 
         pname)

match_data <- rbind(p_map, d_map)

match_data %>% head(3)
## # A tibble: 3 x 2
##   dname    pname   
##   <chr>    <chr>   
## 1 Ha Noi   Ha Noi  
## 2 Ha Giang Ha Giang
## 3 Cao Bang Cao Bang

Sử dụng match_data tạo một vector pc_list chứa tên tỉnh thành (từ pname) và được đánh chỉ số là tên tìm kiếm của cột dname. Chỉ số được biến đổi bằng standardize_pc và sẽ được sử dụng để so sánh khi xử lý dữ liệu raw_df. Với mỗi tên trong province_city của raw_df ta tìm chỉ số trùng trong vector mới này và từ đó biết được tên tỉnh thành tương ứng.

Sau khi standardize_pc, ta cần loại bỏ các phần tử trong vector có chỉ số là "". Trường hợp này xảy ra do dữ liệu tỉnh thành được sử dụng có bao gồm các quận của thành phố Hồ Chí Minh có tên chỉ là số (VD: Quận 1).

pc_list <- match_data$pname

names(pc_list) <- match_data$dname %>% 
  standardize_pc()

pc_list <- pc_list[names(pc_list) != ""]

pc_list %>% head(3)
##      hanoi    hagiang    caobang 
##   "Ha Noi" "Ha Giang" "Cao Bang"

Từ danh sách chỉ số của pc_list ta tạo regular expression dạng (ten1|ten2|...) để xác định xem một xâu ký tự có xâu con nào nằm trong danh sách tên (chỉ số) hay không.

pc_matcher <- paste("(", 
                    paste(names(pc_list), 
                          collapse = "|"), 
                    ")", 
                    sep = "")

pc_matcher
## [1] "(hanoi|hagiang|caobang|backan|tuyenquang|laocai|dienbien|laichau|sonla|yenbai|hoabinh|thainguyen|langson|quangninh|bacgiang|phutho|vinhphuc|bacninh|haiduong|haiphong|hungyen|thaibinh|hanam|namdinh|ninhbinh|thanhhoa|nghean|hatinh|quangbinh|quangtri|thuathienhue|danang|quangnam|quangngai|binhdinh|phuyen|khanhhoa|ninhthuan|binhthuan|kontum|gialai|daklak|daknong|lamdong|binhphuoc|tayninh|binhduong|dongnai|bariavungtau|hochiminh|longan|tiengiang|bentre|travinh|vinhlong|dongthap|angiang|kiengiang|cantho|haugiang|soctrang|baclieu|camau|badinh|hoankiem|tayho|longbien|caugiay|dongda|haibatrung|hoangmai|thanhxuan|hadong|sontay|socson|donganh|gialam|tuliem|thanhtri|melinh|bavi|phuctho|danphuong|hoaiduc|quocoai|thachthat|chuongmy|thanhoai|thuongtin|phuxuyen|unghoa|myduc|hagiang|dongvan|meovac|yenminh|quanba|vixuyen|bacme|hoangsuphi|xinman|bacquang|quangbinh|caobang|baolam|baolac|thongnong|haquang|tralinh|trungkhanh|halang|quanguyen|phuchoa|hoaan|nguyenbinh|thachan|backan|pacnam|babe|nganson|bachthong|chodon|chomoi|nari|tuyenquang|nahang|chiemhoa|hamyen|yenson|sonduong|laocai|batxat|muongkhuong|simacai|bacha|baothang|baoyen|sapa|vanban|dienbienphu|muonglay|muongnhe|muongcha|tuachua|tuangiao|dienbien|dienbiendong|muongang|laichau|tamduong|muongte|sinho|phongtho|thanuyen|tanuyen|sonla|quynhnhai|thuanchau|muongla|bacyen|phuyen|mocchau|yenchau|maison|songma|sopcop|yenbai|nghialo|lucyen|vanyen|mucangchai|tranyen|tramtau|vanchan|yenbinh|hoabinh|dabac|kyson|luongson|kimboi|caophong|tanlac|maichau|lacson|yenthuy|lacthuy|thainguyen|songcong|dinhhoa|phuluong|donghy|vonhai|daitu|phoyen|phubinh|langson|trangdinh|binhgia|vanlang|caoloc|vanquan|bacson|huulung|chilang|locbinh|dinhlap|halong|mongcai|campha|uongbi|binhlieu|tienyen|damha|haiha|bache|vandon|hoanhbo|dongtrieu|yenhung|coto|bacgiang|yenthe|tanyen|langgiang|lucnam|lucngan|sondong|yendung|vietyen|hiephoa|viettri|phutho|doanhung|hahoa|thanhba|phuninh|yenlap|camkhe|tamnong|lamthao|thanhson|thanhthuy|tanson|vinhyen|phucyen|lapthach|tamduong|tamdao|binhxuyen|yenlac|vinhtuong|songlo|bacninh|tuson|yenphong|quevo|tiendu|thuanthanh|giabinh|luongtai|haiduong|chilinh|namsach|kinhmon|kimthanh|thanhha|camgiang|binhgiang|gialoc|tuky|ninhgiang|thanhmien|hongbang|ngoquyen|lechan|haian|kienan|doson|kinhduong|thuynguyen|anduong|anlao|kienthuy|tienlang|vinhbao|cathai|bachlongvi|hungyen|vanlam|vangiang|yenmy|myhao|anthi|khoaichau|kimdong|tienlu|phucu|thaibinh|quynhphu|hungha|donghung|thaithuy|tienhai|kienxuong|vuthu|phuly|duytien|kimbang|thanhliem|binhluc|lynhan|namdinh|myloc|vuban|yyen|nghiahung|namtruc|trucninh|xuantruong|giaothuy|haihau|ninhbinh|tamdiep|nhoquan|giavien|hoalu|yenkhanh|kimson|yenmo|thanhhoa|bimson|samson|muonglat|quanhoa|bathuoc|quanson|langchanh|ngoclac|camthuy|thachthanh|hatrung|vinhloc|yendinh|thoxuan|thuongxuan|trieuson|thieuhoa|hoanghoa|hauloc|ngason|nhuxuan|nhuthanh|nongcong|dongson|quangxuong|gia|vinh|cualo|thaihoa|quephong|quychau|kyson|tuongduong|nghiadan|quyhop|quynhluu|concuong|tanky|anhson|dienchau|yenthanh|doluong|thanhchuong|nghiloc|namdan|hungnguyen|hatinh|honglinh|huongson|ductho|vuquang|nghixuan|canloc|huongkhe|thachha|camxuyen|kyanh|locha|donghoi|minhhoa|tuyenhoa|quangtrach|botrach|quangninh|lethuy|dongha|quangtri|vinhlinh|huonghoa|giolinh|dakrong|camlo|trieuphong|hailang|conco|hue|phongdien|quangdien|phuvang|huongthuy|huongtra|aluoi|phuloc|namdong|lienchieu|thanhkhe|haichau|sontra|nguhanhson|camle|hoavang|hoangsa|tamky|hoian|taygiang|donggiang|dailoc|dienban|duyxuyen|queson|namgiang|phuocson|hiepduc|thangbinh|tienphuoc|bactramy|namtramy|nuithanh|phuninh|nongson|quangngai|binhson|trabong|taytra|sontinh|tunghia|sonha|sontay|minhlong|nghiahanh|moduc|ducpho|bato|lyson|quinhon|anlao|hoainhon|hoaian|phumy|vinhthanh|tayson|phucat|annhon|tuyphuoc|vancanh|tuyhoa|songcau|dongxuan|tuyan|sonhoa|songhinh|tayhoa|phuhoa|donghoa|nhatrang|camranh|camlam|vanninh|ninhhoa|khanhvinh|dienkhanh|khanhson|truongsa|phanrangthapcham|bacai|ninhson|ninhhai|ninhphuoc|thuanbac|thuannam|phanthiet|lagi|tuyphong|bacbinh|hamthuanbac|hamthuannam|tanhlinh|duclinh|hamtan|phuqui|kontum|dakglei|ngochoi|dakto|konplong|konray|dakha|sathay|tumorong|pleiku|ankhe|ayunpa|kbang|dakdoa|chupah|iagrai|mangyang|kongchro|ducco|chuprong|chuse|dakpo|iapa|krongpa|phuthien|chupuh|buonmathuot|buonho|eahleo|easup|buondon|cumgar|krongbuk|krongnang|eakar|mdrak|krongbong|krongpac|krongana|lak|cukuin|gianghia|dakglong|cujut|dakmil|krongno|daksong|dakrlap|tuyduc|dalat|baoloc|damrong|lacduong|lamha|donduong|ductrong|dilinh|baolam|dahuoai|dateh|cattien|dongxoai|phuoclong|binhlong|bugiamap|locninh|budop|honquan|dongphu|budang|chonthanh|tayninh|tanbien|tanchau|duongminhchau|chauthanh|hoathanh|godau|bencau|trangbang|thudaumot|dautieng|bencat|phugiao|tanuyen|dian|thuanan|bienhoa|longkhanh|tanphu|vinhcuu|dinhquan|trangbom|thongnhat|cammy|longthanh|xuanloc|nhontrach|vungtau|baria|chauduc|xuyenmoc|longdien|datdo|tanthanh|condao|thuduc|govap|binhthanh|tanbinh|tanphu|phunhuan|binhtan|cuchi|hocmon|binhchanh|nhabe|cangio|tanan|tanhung|vinhhung|mochoa|tanthanh|thanhhoa|duchue|duchoa|benluc|thuthua|tantru|canduoc|cangiuoc|chauthanh|mytho|gocong|tanphuoc|caibe|cailay|chauthanh|chogao|gocongtay|gocongdong|tanphudong|bentre|chauthanh|cholach|mocaynam|giongtrom|binhdai|batri|thanhphu|mocaybac|travinh|canglong|cauke|tieucan|chauthanh|caungang|tracu|duyenhai|vinhlong|longho|mangthit|vungliem|tambinh|binhminh|traon|binhtan|caolanh|sadec|hongngu|tanhong|hongngu|tamnong|thapmuoi|caolanh|thanhbinh|lapvo|laivung|chauthanh|longxuyen|chaudoc|anphu|tanchau|phutan|chauphu|bien|triton|chauthanh|chomoi|thoaison|rachgia|hatien|kienluong|hondat|tanhiep|chauthanh|gionggieng|goquao|anbien|anminh|vinhthuan|phuquoc|kienhai|uminhthuong|giangthanh|ninhkieu|omon|binhthuy|cairang|thotnot|vinhthanh|codo|phongdien|thoilai|vithanh|ngabay|chauthanha|chauthanh|phunghiep|vithuy|longmy|soctrang|chauthanh|kesach|mytu|culaodung|longphu|myxuyen|nganam|thanhtri|vinhchau|trande|baclieu|hongdan|phuoclong|vinhloi|giarai|donghai|hoabinh|camau|uminh|thoibinh|tranvanthoi|cainuoc|damdoi|namcan|phutan|ngochien|quynhon|hcm|hn|hp|daclac)"

Hàm match_pc thực hiện việc tìm kiếm đó. Hàm này biến đổi xâu nhận được bằng standardize_pc sau đó tìm chỉ số đầu tiên của pc_list trùng với xâu đã dử lý bằng cách kiểm tra với regular expression pc_matcher.

match_pc <- function(pc) {
  match_result <- pc %>% 
    standardize_pc() %>% 
    str_match(pc_matcher)
  pc_list[match_result[,1]]
}
# Ví dụ
c("hcm", "thanhxuanhanoi", "HA LONG, HA TRUNG, THANH HOA") %>% 
  match_pc()
##           hcm     thanhxuan        halong 
## "Ho Chi Minh"      "Ha Noi"  "Quang Ninh"

5 Thực hiện xử lý dữ liệu

result <- raw_df %>%
  mutate(province_city_standard = province_city %>% 
           match_pc()) 
write_xlsx(result, path = "result.xlsx")

result
## # A tibble: 500,000 x 4
##    recid   cus_name                  province_city province_city_standard
##    <chr>   <chr>                     <chr>         <chr>                 
##  1 1       KHACH HANG VANG LAI       Ha Noi        Ha Noi                
##  2 10      DINH CHE TAI CHINH        Ha Noi        Ha Noi                
##  3 100     VPBANK                    <NA>          <NA>                  
##  4 1000    CONG TY TNHH SAO BAC VIET <NA>          <NA>                  
##  5 10000   LE CAO TY                 Ha Noi        Ha Noi                
##  6 100000  HO QUANG PHU              Can Tho       Can Tho               
##  7 1000000 DUONG MINH HOA            An Giang      An Giang              
##  8 1000002 TRAN VAN TRUONG           Hai Duong     Hai Duong             
##  9 1000003 NGUYEN MANH HO            Ha Noi        Ha Noi                
## 10 1000004 DUONG THI TINH GIANG      Da Nang       Da Nang               
## # ... with 499,990 more rows