iT邦幫忙

2023 iThome 鐵人賽

DAY 7
0
AI & Data

用R語言玩轉文字探勘系列 第 7

[Day 7] R語言中的字串資料、路徑與編碼

  • 分享至 

  • xImage
  •  

R語言中的字串資料

前面章節「總統演說」的範例中,能看到R語言中常見的文字資料格式,要不是儲存在dataframe中,每筆資料都是文章、段落、句子,或者是用list將文章存在每一個元素中。不過,文字資料其實有著許多眉角,這個章節會談編碼、匯入和匯出三件事情,希望減少你的踩雷機會。

路徑與編碼

路徑

我們先來複習路徑(path)的概念,以免後續匯入資料時出現問題。無論是R語言,或者是其他程式語言,甚至是整體電腦科學,都有路徑這個專有名詞,它指的是檔案所在地址。

路徑可以分為絕對路徑相對路徑,前者很直觀,就是完整地址,例如"/Users/rlover/textmining/data/encoding.csv";後者則是現在所處檔案路徑和檔案所在位置的相對關係,舉例來說,我現在正開啟"/Users/rlover/textmining/這個專案,從我站的位置看起來,剛剛那個檔案的相對路徑就會是"data/encoding.csv"

為什麼要知道路徑?就像平常寫信要知道地址一樣,讀取資料時也需要路徑,通常匯入資料的函數中,會有一個參數要指名路徑。

那麼,要怎麼取得路徑呢?除了堅持老派的手寫溫度,自己一個一個字輸入以外,還有什麼辦法?
* Mac:右鍵 再按 options or option + command + c
* Windows:shift 再按 右鍵 or ctrl + L
* Windows:直接從 address bar or file explorer 複製
* reference:Mac & Windows

  • 路徑中的斜線與反斜線: Mac copy 得到的路徑用 /間隔,可以直接使用,Windows copy 得到的路徑用 \間隔,不能直接用,要修正成 / or \\"data/a.csv" or "data\\a.csv" 都可以

至於路徑的「語言」,基本上使用英文一定沒問題,但若路徑中包含中文,就有可能出錯,即使現在沒問題,也不代表以後沒問題,尤其是 Windows 非常煩人。建議將R和RStudio安裝在英文路徑中,且使用者名稱用英文。

路徑相對好改,因為只要修改檔案名稱或資料夾名稱就好,但想修改使用者名稱,只能新創英文帳號,若還是想用中文,可以設置環境變數

另外,在R語言中時常會遇到權限問題,建議R和RStudio不要安裝在Windows的OneDrive資料夾,.R檔案或.Rmd檔案最好不要放在自動跟雲端硬碟同步的資料夾,譬如Google Drive 或是 Dropbox 都有危險。

當你需要讀取大量、位置四散各地的文字檔案時,上面這些建議說不定就會派上用場,因此可以先將有個章節談這件事情,放在心上,有需要的時候再回來看。

編碼

在認識如何匯入與匯出文字資料前,得先認識何謂字元編碼(character
encoding)。我們知道電腦用 0,1
儲存資訊,字元編碼就是利用數字代表文字與符號。

ASCII
編碼
為例,它由美國制定,用來對應英文符號與二進制,大約可以表示128 個文字符號和數字之間的關係。舉例來說,A 的編碼是65,也就是二進制中的01000001,但如果享用ANCII表達英文以外語言例如中文,會遇上兩個問題。

第一,ASCII編碼的符號不夠,例如naïve的ï就不在其中,需要新的編碼才能處理。第二,不同國家的符號與二進制對應方式不同,例如é vs. ג (法 vs. 希),就是一個實例。

若改看ANSI編碼,它是Windows作業系統上的code page,對應到預設編碼,也就是說,它會因應當前系統區域(locale)決定使用編碼,像是繁體中文對應 BIG5,簡體中文對應GB2312,日文可能是JIS。不過,當台灣人存ANSI時代表以BIG5編碼儲存,可是日本人打開打開記事本的時候,ANSI判斷後會用JIS解碼,儲存時的編碼和讀取時設定的編碼方式不同,因此出現亂碼。

還有其他選擇嗎?我們還有另一種厲害武器,稱為Unicode,它是一種納入所有字元的萬國碼,收錄上百萬個文字與符號,稱為字符集(character set),例如U+963f 代表 U+4E25代表U+0041代表 A

它只規定對應方式(集合 set),沒規定儲存方式(編碼,encoding),例如U+4E254E25轉成二進制為100111000100101,15位元,因此能夠涵蓋幾乎所有字元,解決前述提的編碼不夠、出現亂碼等問題。然而,它也面臨挑戰,包含長度問題,例如原本128個符號用8個位元儲存,現在要使用兩倍長度的位元才能達成,同時還有辨識問題,我們很難分辨如何確知是用一個還是兩個符號拼在一起。

想要解決這個問題,就需要轉成二進制的儲存方式,而UTF-8編碼,就是其中一種解方。它的長度彈性,前綴數字表示長度,後面數字代表符號,且涵蓋ASCII的編碼,是目前網頁採用的編碼主流,2008年超過60%、2015年更超過80%網頁都在使用。

了解編碼的簡單歷史後,我們要進到下一個重要議題:亂碼。

不只是在R語言中探勘文字資料,生活中就有諸多會遇到亂碼的場景。有時候打開電子郵件、將資料匯入至Excel,甚至是用記事本和notepad++,都會遇到亂碼問題。從上面介紹中我們知道,亂碼會出現,就是因為儲存時的編碼和讀取時設定編碼不同。

在R或者RStudio遇到亂碼時,應該怎麼處理?首先,我們要判斷問題起因,到底是個別檔案問題,還是R語言或者RStudio的環境問題,又或者是系統編碼設定問題?底下我們整理不同問題的解決方式供你參考。

  • 個別檔案的編碼問題(預設以RStudio開啟)
    • .R or .Rmd 的亂碼
      1. 檢查編碼方式:x <- '中文'; Encoding(x)
      2. 什麼都不設定,會用系統預設的編碼讀取檔案,底下討論
      3. 調整預設編碼 or 以 UTF8 編碼開啟檔案,請參考連結第一部分,主要是調設定
    • 讀取 .csv or .txt 的亂碼:建議都改成 UTF8
      1. 手動更改編碼 e.g. 在記事本裡面另存成其他編碼
      2. 讀取檔案時在函數中設定編碼 e.g. read.csv() 裡面的參數fileEncoding = "UTF-8"
      3. 讀進檔案後再轉碼
        e.g. df <- readLines("a.CSV", encoding="big5");df <- iconv(df, "big5", "utf8")
  • R/RStudio 的編碼問題
    • R console 中文變亂碼:上網查原因 e.g. R 版本太新
    • R Studio 某些預覽有問題:上網查原因 e.g. 開發的bug(2021年中文出現災情)
    • 圖片預覽中文無法顯示:字體問題 (尤其Mac),可以用設定正確字體解決
  • 系統編碼問題
    • 讀檔的編碼改了依然有中文亂碼:R 會用系統的預設編碼
    • 利用 Sys.getlocale() 查看編碼,利用 Sys.setlocale() 更改編碼,兩個參數,category代表要修改的類別locale
      代表系統區域
    • 不同作業系統
      1. Mac:Sys.setlocale(category = "LC_ALL", locale = "UTF-8")
      2. Win:Sys.setlocale(category = "LC_ALL", locale = "cht")

最後統整上面段落的資訊,免得看了眼花撩亂:

  • Windows 很不友善、路徑跟檔案名稱最好都英文
  • 編碼有很多種,能用 UTF-8 就用 UTF-8
  • 亂碼可能是檔案編碼、R/RStudio 的 bug、系統預設編碼
  • .R 亂碼調整 file encoding
  • 讀 csv 可以手動調整、讀取時設定、讀取後轉換
  • 顯示中文有問題可能是 bug,或是要調整系統編碼

匯入文字資料

前面提到,匯入檔案時,編碼可能出現問題,因此我們可以在匯入前,先用notepad++、記事本、Excel等文書處理工具觀察檔案。當然,你也可以懶得打開其他程式,直接用R讀讀看,跟資料拼了,聽起來非常熱血。

不過如果欄位名稱為中文,編碼又設定錯誤,很遺憾地我們無法匯入資料,連觀察編碼都沒機會,這時候就真的要先用文書軟體打開確認;若欄位名稱為英文,只是編碼錯誤,那就可以匯進R語言後再修改編碼。

總結來看,我們有三種方法處理亂碼問題,第一是直接用文書軟體修改原始檔案編碼,第二是讀取檔案時設定參數,第三是讀取時不管亂碼,等資料進到R語言環境後再來修改編碼

底下來看實際範例。第一個範例中,我們使用109Q1實價登錄資料,這個檔案的欄位名稱和資料內容都是中文,但編碼不是readr匯入資料函數預設的UTF8。

# 直接讀遇上錯誤
df_land_109Q1_test <- read_csv("data/109Q1_a_lvr_land_a_build.csv")
# Error in make.names(x) : invalid multibyte string at '<bd>s<b8><b9>'
# 設定參數,編碼為BIG5,就可以讀了
df_land_109Q1_test <- read_csv("data/109Q1_a_lvr_land_a_build.csv", 
                               locale = locale(encoding = "BIG5"))

第一個範例中,我們使用各縣市用電資料
,這個檔案的欄位名稱是英文,讀取沒有問題,但資料內容都是中文,再次遇到亂碼。

# 直接讀遇上沒錯但遇到亂碼
df_electricity_usage_test <- read_csv("data/electricity_usage.csv")
# 讀進來後修改編碼就搞定
df_electricity_usage_test$county <- 
  iconv(df_electricity_usage_test$county, 
        from = "BIG5", to = "UTF8")

從上面例子看R語言匯入資料可能遇上的問題。現在環境下大部分資料都用UTF8編碼儲存,因此平常不太會踩雷,但若是政府開放資料,就會時常遇到BIG5,簡體中文還有其他編碼,使用時要多加注意。

匯出文字資料

談完匯入,我們改看匯出。最常見的格式如.csv,一般也是用readr::write_**()相關函數匯入資料,預設輸出編碼和輸入一樣,都是以UTF8為編碼,因此可以替我們省下很多心力。

不過,在看傳統程式碼的時候,除了base R體系的write.**()函數以外,我們還會另外看到R語言中兩個內建函數,可以拿來讀寫
R 的物件。

  • 單一物件 .rds:readRDS()/saveRDS() or
    readr::read_rds()/write_rds()
    • write_rds(mtcars, "data/mtcars.rds")
  • 很多物件 .RData:save() or load()
    • e.g. save(data1, data2, file = "data/d0102.RData")
file_r <- "data/"
a <- 1
b <- 2

### export
write_rds(a, str_c(file_r, "a.rds"))
save(a, b, file = str_c(file_r, "a_b.RData"))

### load
a_check <- read_rds(str_c(file_r, "a.rds"))

rm(a)
rm(b)
load(file = str_c(file_r, "a_b.RData"))

進行文字探勘前,我們要先匯入資料,匯入時要考慮文字編碼。匯入後,我們要確保文字資料的儲存格式,因為不同框架有各自習慣的資料結構。文字探勘完成後,我們會匯出資料,這時候要考慮以何種檔案格式匯出,同時也會確認編碼設定無誤。這些就是在R語言中和文字資料交手時,要注意的眉角!


上一篇
[Day 6] R語言與字串處理: 利用stringr
下一篇
[Day 8] 以R語言分詞 - 概念篇
系列文
用R語言玩轉文字探勘30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言