第 1 章 Data cleaning

1.1 data frame

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
StuDF <- data.frame(
次序=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)
)
StuDF 
class(StuDF)
typeof(StuDF)
length(StuDF) # 從向量角度看
nrow(StuDF) # 從矩陣角度看

1.2 dplyr套件

• 針對data frame的資料處理套件
library(dplyr)

str(StuDF)

head(StuDF)

tail(StuDF)

1.2.1 slice：切割資料行

StuDF
slice(StuDF,1:3)
slice(StuDF,4:5)
slice(StuDF,n())

slice(StuDF,(n()-1):n())
StuDF
slice(StuDF,-5:-7)
-5:-7
slice(StuDF,c(-5,-6,-7))

library(readr)
collegeData <- read_csv("https://raw.githubusercontent.com/tpemartin/github-data/master/103_student.csv")
• 檢查變數結構

• 顯示前4筆，後3筆，中間第101到110筆。

1.2.2 mutate：產生變數

StuDF
mutate(StuDF,
調分後成績=成績+10)
transmute(StuDF,
調分後成績=成績+10) # 不保留其他變數

StuDF
mutate(StuDF,
調分後成績=成績+10) -> StuDF

StuDF
StuDF <- mutate(StuDF,
調分後成績=成績+10) 

StuDF$成績+10 在collegeData: • 新增變數男生女生,其值為「一到四年級」所有男生及女生的加總。（男生使用dplyr, 女生不使用dplyr） • 新增變數男女生比，其值為前述男生/女生。 變數運算，前步驟出現的新變數，後步驟可直接拿來用。 1.2.3 summarise：計算特徵值 StuDF summarise(StuDF, 平均成績=mean(成績), 最高分=max(成績), 最低分=min(成績)) summarise()會回傳一個data frame，其變數為計算特徵變數。 以上計算若把summarise改成mutate結果會如何？ 若老師的調分為原始成績加上「最高最低分差距除以5」，請產生調分成績: 1.2.4 select：選擇變數 StuDF mutate(StuDF, 平均成績=mean(成績), 最高分=max(成績), 最低分=min(成績)) -> StuDF2 StuDF2 names(StuDF2) select(StuDF2, 姓名,學號,成績,調分後成績) select(StuDF2, -次序,-性別,-最高分,-最低分) 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. select(StuDF2, 次序,性別, contains("最")) select(StuDF2, -次序,-性別, -contains("最")) 選出collegeData中所有男生變數： select(collegeData, contains("男生")) 1.2.5 filter：條件選取觀測值 Logical predicates StuDF # logical vector logiChoose <- c( F,F,F,T,T,F,T,F ) # 使用logical vector選擇所要觀測值"女" StuDF[logiChoose,] which()可顯示向量元素為真的位置。 logiChoose which(logiChoose) slice( StuDF,which(logiChoose) ) 使用logical predicate產生logical vector StuDF$性別=="女" # logical predicate

logiChoose <- StuDF$性別=="女" StuDF[logiChoose,] 常見的logical predicate可由以下兩者產生： 女性，且成績大於60 # relational operators StuDF$性別=="女"
StuDF$成績>60 # combined with logical operator (StuDF$性別=="女" & StuDF\$成績>60) -> logiChoose2
logiChoose2

StuDF[logiChoose2,]

使用filter

• filter(data frame, logical predicates)
StuDF
filter(StuDF,
性別=="女")
filter(StuDF,
(性別=="女" & 成績>60))
filter(StuDF,
性別=="女",
成績>60) # 多個AND條件可用,分隔

• 女性平均成績最高分最低分

• 男性平均成績最高分最低分

1. 縣市名稱為“30 臺北市”

2. 縣市名稱為“30 臺北市”或“01 新北市”。（使用OR|或belong to%in%

1.2.6 group_by：分群計算

• group_by(data frame,分群變數)

計算不同性別之平均成績及最高/低分

group_by(StuDF,
性別) -> StuDF_by性別

# 使用grouped data frame
summarise(StuDF_by性別,
平均成績=mean(成績),
最高分=max(成績),
最低分=min(成績))

# 使用ungrouped data frame
summarise(StuDF,
平均成績=mean(成績),
最高分=max(成績),
最低分=min(成績))

男女調分不同

• 各加其群組之「最高減最低分除以5」
mutate(
StuDF_by性別,
最高分=max(成績),
最低分=min(成績),
調分大小=(最高分-最低分)/5,
調分後成績=成績+調分大小
) -> StuDF_依性別調分
StuDF_依性別調分

依性別成績分

group_by(StuDF,
性別,
(成績>75)) -> StuDF_by性別成績

summarise(StuDF_by性別成績,
平均成績=mean(成績),
人數=n())

mutate/transmute/summarise

• 若input為grouped data frame，其output也會是grouped data frame.

• output若接著用，也會是分群計算的結果。

• 最好習慣接著ungroup

ungroup(StuDF_依性別調分) ->
StuDF_調分後

1.3 Pipe operator

group_by(StuDF,
性別) -> StuDF_by性別

mutate(
StuDF_by性別,
最高分=max(成績),
最低分=min(成績),
調分大小=(最高分-最低分)/5,
調分後成績=成績+調分大小
) -> StuDF_依性別調分

ungroup(StuDF_依性別調分) ->
StuDF_調分後

%>% pipe operator:

1. 預設：%>% 把它左邊（LHS）的物件流入它右邊（RHS）函數的argument第一個位置。 )

2. 若要流入右邊函數的「非」第一位置argument，則用.在右邊函數中標示。

3. %>% 可進行串接，則下一個%>%會以上個函數輸出結果當做新的LHS物件。

# 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_調分後

StuDF %>% group_by(
性別)  %>%
mutate(
最高分=max(成績),
最低分=min(成績),
調分大小=(最高分-最低分)/5,
調分後成績=成績+調分大小
)  %>% ungroup() ->
StuDF_調分後

StuDF %>% # 將StuDF
group_by(性別) %>% # 依性別分群
mutate( # 接著計算各群的:
最高分=max(成績),
最低分=min(成績),
調分大小=(最高分-最低分)/5,
調分後成績=成績+調分大小
)  %>%
ungroup() -> # 接著ungroup後輸出
StuDF_調分後

• 等級別,縣市名稱分群後,

• 計算一年級男/女生比例後,

• 找出男女生比例最高的等級別,縣市名稱組合。

load(url("https://www.dropbox.com/s/duh5aaqgl2f5m3z/loopTranscriptData.Rda?raw=1"))

c('學號','學屆','學系','學年','學期','學期成績','學分數','必選修類別（必∕選∕通）') -> names(transcriptDataFinal)
1. 計算每位學生每學期的平均成績。

2. 計算每位學生每學期學分數在必/選/通 三類的學分數比重。

3. 學屆為100（即100學年入學）的學生，各系學生在學所修總學分數之中位數，何系最高？

library(tidyr)

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
)
df_gatherExample
gather(df_gatherExample,
1999,2000,
key="年份",value="人口")

gather中的變數選擇可使用select helpers.

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. 將資料「一～十二月」縮排在月份變數，而其下的對應值縮排在對數變數。

2. 計算每個月份桃園總結婚對數。

3. 找出每個地區結婚最高峰月份。

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對應值

df_spreadExample
var,value)

collegeData_gather %>%
類別,人數
)

1. 每筆資料之男生總數、女生總數、學生總數

2. 每個學校之男生總數、女生總數、學生總數

(hint: stringr套件裡str_detect(向量,文字特徵)可偵測向量裡每個元素是否包含某文字特徵。)

df_twbankExchangeRate <- read_csv("http://www.bot.com.tw/Govinfo/opendata/csv/151/20180101-20181231-FXCRT.csv")

1.5 變數類別調整

data frame的每個變數均為atomic vector，而atomic vector的class會影響之後作圖的合理性，故作圖前要先確保每個變數的class正確性：

1.6 Data import

2. 貼上檔案下載網址或選電腦檔案

3. Locale: configure…>Encoding

Import Dataset失效，可以改以read_lines()先將文字檔內容原封不動讀入，再使用iconv()來嘗試各種編碼轉換組合，都沒問題才使用read_csv()讀入。

• 編碼格式: BIG5

library(readr); library(dplyr)
# 線上引入原始資料成字串向量
read_csv() -> data2
iconvlist()