介紹如何將 data frame 中的一欄文字,依據分隔符號切割成多個不同的欄位。
假設我們現在有一個 data frame,其資料如下:
# 原始資料 raw.df <- data.frame( name = c("Mary", "Joe", "John"), info = c("54.5;172;56", "63.2;179;45", "49.2;168;38") ) raw.df
name info 1 Mary 54.5;172;56 2 Joe 63.2;179;45 3 John 49.2;168;38
其中 info
欄位中儲存了體重、身高與年紀三項數值,但是這些資料以分號(;
)分隔,都放在同一個 info
欄位中,沒辦法直接取用。
strsplit
函數若要將字串依據指定分隔符號,分割成多個子字串,傳統上可以使用 strsplit
函數,不過其得到的結果是一個列表(list),使用上並不是非常方便:
# 單純分割字串(不好用!) strsplit(as.character(raw.df$info), ";")
[[1]] [1] "54.5" "172" "56" [[2]] [1] "63.2" "179" "45" [[3]] [1] "49.2" "168" "38"
stringr
套件若在分割欄位為固定數量的情況下,stringr
套件的 str_split_fixed
函數可以直接將結果轉為字串的矩陣:
library(stringr) # 將每一字串分割成 3 欄 str_split_fixed(raw.df$info, ";", 3)
[,1] [,2] [,3] [1,] "54.5" "172" "56" [2,] "63.2" "179" "45" [3,] "49.2" "168" "38"
tidyr
套件若要將 info
欄位以分號分割成三個欄位,並且直接放進原 data frame 中,可以使用 tidyr
套件所提供的 separate
函數:
library(tidyr) # 將每一字串分割成 3 欄,並新增至 Data Frame 中 new.df <- separate(raw.df, info, c("weight", "height", "age"), ";") new.df
name weight height age 1 Mary 54.5 172 56 2 Joe 63.2 179 45 3 John 49.2 168 38
這樣就會將原本的 info
欄位替換為新的 weight
、height
與 age
。不過這些資料預設還是會保持字串的型態:
# 檢視資料結構 str(new.df)
'data.frame': 3 obs. of 4 variables: $ name : Factor w/ 3 levels "Joe","John","Mary": 3 1 2 $ weight: chr "54.5" "63.2" "49.2" $ height: chr "172" "179" "168" $ age : chr "56" "45" "38"
若想讓它自動轉換為數值或布林值,可以加上 convert = TRUE
參數:
# 將每一字串分割成 3 欄,並新增至 Data Frame 中 new.df.conv <- separate(raw.df, info, c("weight", "height", "age"), ";", convert = TRUE) # 檢視資料結構 str(new.df.conv)
'data.frame': 3 obs. of 4 variables: $ name : Factor w/ 3 levels "Joe","John","Mary": 3 1 2 $ weight: num 54.5 63.2 49.2 $ height: int 172 179 168 $ age : int 56 45 38
這樣就可以快速將一欄字串分割成多個欄位,進行後續的分析了。
參考資料:StackOverflow