第 1 章 Data cleaning
1.1 data frame
R的物件都是向量,分成atomic vector(使用
c()
創立)及list兩大類(使用list()
創立 ): https://bookdown.org/tpemartin/ntpu-programming-for-data-science/vectors.html#two-types-of-vectorsdata frame是list的特例:
- 每個元素為等長atomic vector。
範例資料
StuList <- list(
次序=c(1,2,3,4,5,6,7,8),
學號=c(172,214,322,425,517,833,752,114),
姓名=c("小明","大雄","胖虎","小新","大白","阿華","小英","阿美"),
性別=c("男","男","男","女","女","男","女","男"),
成績=c(80,42,90,82,50,77,30,90)
)
StuList
as.data.frame(StuList) -> StuDFfromList
StuDFfromList
1.2 dplyr套件
- 針對data frame的資料處理套件
檢查變數結構
檢查前6筆
檢查後6筆
1.2.1 slice:切割資料行
依row位置選擇資料
使用slice
顯示最後2筆資料。
政府開放平台:106學年大專院校校別學生數
library(readr)
collegeData <- read_csv("https://raw.githubusercontent.com/tpemartin/github-data/master/103_student.csv")
檢查變數結構
- 顯示前4筆,後3筆,中間第101到110筆。
1.2.2 mutate:產生變數
若要更動原data frame內容,記得要回存:
或
不使用dplyr則必需使用$
取出變數向量後,進行運算再回存到data frame裡新的變數裡:
在collegeData:
新增變數男生及女生,其值為「一到四年級」所有男生及女生的加總。(男生使用dplyr, 女生不使用dplyr)
新增變數男女生比,其值為前述男生/女生。
變數運算,前步驟出現的新變數,後步驟可直接拿來用。
1.2.3 summarise:計算特徵值
summarise()
會回傳一個data frame,其變數為計算特徵變數。
以上計算若把summarise
改成mutate
結果會如何?
若老師的調分為原始成績加上「最高最低分差距除以5」,請產生調分成績:
1.2.4 select:選擇變數
select
可搭配select helpers:
starts_with(): Starts with a prefix.
ends_with(): Ends with a suffix.
contains(): Contains a literal string.
matches(): Matches a regular expression.
num_range(): Matches a numerical range like x01, x02, x03.
one_of(): Matches variable names in a character vector.
everything(): Matches all variables.
last_col(): Select last variable, possibly with an offset.
選出collegeData中所有男生變數:
1.2.5 filter:條件選取觀測值
Logical predicates
StuDF
# logical vector
logiChoose <- c(
F,F,F,T,T,F,T,F
)
# 使用logical vector選擇所要觀測值"女"
StuDF[logiChoose,]
which()
可顯示向量元素為真的位置。
使用logical predicate產生logical vector
常見的logical predicate可由以下兩者產生:
女性,且成績大於60
使用filter
filter(data frame, logical predicates)
StuDF
filter(StuDF,
性別=="女")
filter(StuDF,
(性別=="女" & 成績>60))
filter(StuDF,
性別=="女",
成績>60) # 多個AND條件可用,分隔
請計算StuDF中:
女性平均成績,最高分,最低分
- 男性平均成績,最高分,最低分
依以下各別情境,選出collegeData中符合情境的觀測值:
縣市名稱為“30 臺北市”
縣市名稱為“30 臺北市”或“01 新北市”。(使用OR
|
或belong to%in%
)
1.2.6 group_by:分群計算
group_by(data frame,分群變數)
產生grouped data frame,用在mutate/transmute/summarise時會產生分群計算效果。
計算不同性別之平均成績及最高/低分
男女調分不同
- 各加其群組之「最高減最低分除以5」
依性別成績分
依性別及成績是否大於75分:
mutate/transmute/summarise
若input為grouped data frame,其output也會是grouped data frame.
output若接著用,也會是分群計算的結果。
最好習慣接著ungroup
計算collegeData中不同縣市名稱及體系別的一年級男生及一年級女生總數(使用sum
)和學校數目。
1.3 Pipe operator
group_by(StuDF,
性別) -> StuDF_by性別
mutate(
StuDF_by性別,
最高分=max(成績),
最低分=min(成績),
調分大小=(最高分-最低分)/5,
調分後成績=成績+調分大小
) -> StuDF_依性別調分
ungroup(StuDF_依性別調分) ->
StuDF_調分後
%>%
pipe operator:
預設:
%>%
把它左邊(LHS)的物件流入它右邊(RHS)函數的argument第一個位置。 )若要流入右邊函數的「非」第一位置argument,則用
.
在右邊函數中標示。%>%
可進行串接,則下一個%>%
會以上個函數輸出結果當做新的LHS物件。
根據串接原則1:
# group_by(StuDF,
# 性別) -> StuDF_by性別
StuDF %>% group_by(
性別) -> StuDF_by性別
# mutate(
# StuDF_by性別,
# 最高分=max(成績),
# 最低分=min(成績),
# 調分大小=(最高分-最低分)/5,
# 調分後成績=成績+調分大小
# ) -> StuDF_依性別調分
StuDF_by性別 %>%
mutate(
最高分=max(成績),
最低分=min(成績),
調分大小=(最高分-最低分)/5,
調分後成績=成績+調分大小
) -> StuDF_依性別調分
# ungroup(StuDF_依性別調分) ->
# StuDF_調分後
StuDF_依性別調分 %>% ungroup() ->
StuDF_調分後
依串接原則3:
StuDF %>% group_by(
性別) %>%
mutate(
最高分=max(成績),
最低分=min(成績),
調分大小=(最高分-最低分)/5,
調分後成績=成績+調分大小
) %>% ungroup() ->
StuDF_調分後
串接使得語法更貼近人類語言:
StuDF %>% # 將StuDF
group_by(性別) %>% # 依性別分群
mutate( # 接著計算各群的:
最高分=max(成績),
最低分=min(成績),
調分大小=(最高分-最低分)/5,
調分後成績=成績+調分大小
) %>%
ungroup() -> # 接著ungroup後輸出
StuDF_調分後
將collegeData,
依等級別,縣市名稱分群後,
計算一年級男/女生比例後,
- 找出男女生比例最高的等級別,縣市名稱組合。
執行以下程序取得transcriptDataFinal:
若transcriptDataFinal的變數名稱在你電腦為亂碼,請再執行以下程序行:
計算每位學生每學期的平均成績。
計算每位學生每學期學分數在必/選/通 三類的學分數比重。
- 學屆為100(即100學年入學)的學生,各系學生在學所修總學分數之中位數,何系最高?
1.4 gather and spread
1.4.1 gather
df_gatherExample <- data.frame(
country=c("A","B","C"),
`1999`=c("0.7k","37k","212k"),
`2000`=c("2k","80k","213k"),
check.names = F
)
gather中的變數選擇可使用select helpers.
將collegeData裡各年級男女生人數合成兩個欄位,類別,人數,其中類別值為原始欄位名稱(即一年級男生,一年級女生,…等等),而人數則為對應人數。
下載以下民國107年桃園各地區每月結婚對數:
library(readr)
df_taoyuanMarriage <- read_csv("https://data.tycg.gov.tw/opendata/datalist/datasetMeta/download?id=f95d1a33-ec56-44c5-a9ec-3afba8157e39&rid=fd2070ef-7431-4f9c-bc3a-82d7bfbcd2fb")
將資料「一~十二月」縮排在月份變數,而其下的對應值縮排在對數變數。
計算每個月份桃園總結婚對數。
找出每個地區結婚最高峰月份。
1.4.2 spread
df_spreadExample <- data.frame(
id = c(1,1,1,2,2,2),
var = c("花朶萼片長度", "學名", "總類數"),
value = c(5.1, "setosa", 1,
7.0, "versicolor", 2))
將var變數依其值展開成不同欄位名稱,而欄位下所對應的值則為value對應值
將前一個練習的gather data frame還原。
由collegeData計算:
每筆資料之男生總數、女生總數、學生總數
每個學校之男生總數、女生總數、學生總數
(hint: stringr套件裡str_detect(向量,文字特徵)
可偵測向量裡每個元素是否包含某文字特徵。)
下載台銀2018年各交易日收盤匯率:
留下日期、幣別、即期買入匯率,將幣別依其貨幣名稱spread成不同欄位,其下所屬值為即期買入匯率。
1.5 變數類別調整
data frame的每個變數均為atomic vector,而atomic vector的class會影響之後作圖的合理性,故作圖前要先確保每個變數的class正確性:
numeric:
as.numeric
/as.double
integer:
as.integer
factor:
as.factor
請將df_twbankExchangeRate的變數class做適當的修正。
1.6 Data import
以下以文字檔為例:
Environment>Import Dataset>From text(readr)
貼上檔案下載網址或選電腦檔案
Locale: configure…>Encoding
台灣中文資料常使用Windows BIG5編碼,然而它並不是國際標準的BIG5,有時encoding你選BIG5還是有亂碼,此時可以試試CP950,或ISO-8859系列編碼。
若Import Dataset失效,可以改以read_lines()
先將文字檔內容原封不動讀入,再使用iconv()
來嘗試各種編碼轉換組合,都沒問題才使用read_csv()
讀入。
政府資料開放平台:每日外幣參考匯率 > 檢視資料
- 編碼格式: BIG5
以下範例將原始資料轉成UTF8編碼的csv檔儲存
library(readr); library(dplyr)
# 線上引入原始資料成字串向量
read_lines("http://www.taifex.com.tw/data_gov/taifex_open_data.asp?data_name=DailyForeignExchangeRates") ->
originalLines
# 將字串由CP950編碼改成UTF8再讀成data frame data2
originalLines %>%
iconv(from="CP950",to="UTF8") %>%
read_csv() -> data2
BIG5編碼也有數種,視中文語系地區而不同。對於世界不同語系,R可處理那些編碼可由以下指令查詢:
iconvlist()