R
的dplyr
的套件中的指令,包括select
、filter
、
mutate
等函數,協助研究者整理資料,並且轉置資料。例如:library(dplyr)
file <- here::here('data', 'studentsfull.txt')
students<-read.table(file, sep='', header=TRUE)
students.part<-mutate(students, sex=as.numeric(Gender)-1)
students.part
## ID Name Department Score Gender sex
## 1 10322011 Ariel Aerospace 78 F NA
## 2 10325023 Becky Physics 86 F NA
## 3 10430101 Carl Journalism 69 M NA
## 4 10401032 Dimitri English 83 M NA
## 5 10307120 Enrique Chemistry 80 M NA
## 6 10207005 Fernando Chemistry 66 M NA
## 7 10305019 George Mechanics 75 F NA
## 8 10305022 Howell Mechanics 81 M NA
## 9 10305029 Ian Mechanics 60 M NA
## 10 10305031 Julio Mechanics 89 M NA
## 11 10322014 Kaori Aerospace 82 F NA
## 12 10425026 Luke Physics 88 M NA
## 13 10401022 Miguel English 92 M NA
## 14 10501006 Neo English 77 M NA
## 15 10321010 Olivia Economics 85 F NA
## 16 10321011 Peter Economics 88 M NA
## 17 10405017 Qing Mechanics 88 F NA
## 18 10422007 Ricky Aerospace 91 M NA
## 19 10422008 Seiko Aerospace 80 F NA
## 20 10430005 Terresa Journalism 62 F NA
## 21 10530009 Usla Journalism 87 F NA
## 22 10421001 Vivian Economics 70 F NA
## 23 10307018 Wendy Chemistry 85 F NA
## 24 10425003 Xing Physics 93 M NA
## 25 10221030 Yoko Economics 66 F NA
## 26 10430015 Zoe Journalism 92 F NA
R
的基礎指令,而dplyr
提供許多指令幫我們整理資料。Hadley
Wickman
發展了plyr
套件,然後又發展dplyr
套件。為了節省時間,我們直接討論dplyr
的幾個實用的函數。dplyr
套件之後,請嘗試這個指令:## # A tibble: 5 × 4
## s x y z
## <chr> <int> <dbl> <dbl>
## 1 all 1 1 2
## 2 at 2 1 3
## 3 air 3 1 4
## 4 age 4 1 5
## 5 angle 5 1 6
## # A tibble: 5 × 4
## s x y z
## <chr> <int> <dbl> <dbl>
## 1 all 1 1 2
## 2 at 2 1 3
## 3 air 3 1 4
## 4 age 4 1 5
## 5 angle 5 1 6
library(foreign)
file <- here::here('data', 'PP0797B2.sav')
pp0797b2<-read.spss(file, to.data.frame=TRUE)
tibble_pp0797b2<-as_tibble(pp0797b2)
head(tibble_pp0797b2)
## # A tibble: 6 × 24
## Q1 Q2 Q3 Q4 Q5 Q6 Q7 Q8 Q9 Q10 partyid PARTY
## <fct> <fct> <fct> <fct> <fct> <fct> <fct> <fct> <fct> <fct> <fct> <fct>
## 1 很難說 同意 不同… 同意 同意 不同… 同意 不相… 不同… 不同… 國民黨 偏國…
## 2 非常不同意 非常… 不同… 同意 很難… 不同… 不同… 不相… 不同… 不同… 中立及… 中立…
## 3 非常不同意 非常… 非常… 非常… 同意 非常… 不同… 不相… 不同… 不同… 中立及… 中立…
## 4 同意 同意 不同… 同意 不同… 非常… 不同… 很難… 不同… 非常… 民進黨 普通…
## 5 非常不同意 同意 不同… 不同… 不同… 不同… 同意 不相… 同意 非常… 國民黨 非常…
## 6 不同意 不同… 同意 同意 同意 同意 同意 不相… 不同… 非常… 中立及… 中立…
## # ℹ 12 more variables: tondu <fct>, ethnic <fct>, age <fct>, edu <fct>,
## # sengiF <fct>, sengiM <fct>, CAREER <fct>, CAREER8 <fct>, TOWNID <dbl>,
## # arear <fct>, sex <fct>, w <dbl>
## # A tibble: 2,058 × 24
## Q1 Q2 Q3 Q4 Q5 Q6 Q7 Q8 Q9 Q10 partyid PARTY
## <fct> <fct> <fct> <fct> <fct> <fct> <fct> <fct> <fct> <fct> <fct> <fct>
## 1 很難說 同意 不同… 同意 同意 不同… 同意 不相… 不同… 不同… 國民黨 偏國…
## 2 非常不同意 非常… 不同… 同意 很難… 不同… 不同… 不相… 不同… 不同… 中立及… 中立…
## 3 非常不同意 非常… 非常… 非常… 同意 非常… 不同… 不相… 不同… 不同… 中立及… 中立…
## 4 同意 同意 不同… 同意 不同… 非常… 不同… 很難… 不同… 非常… 民進黨 普通…
## 5 非常不同意 同意 不同… 不同… 不同… 不同… 同意 不相… 同意 非常… 國民黨 非常…
## tondu ethnic age edu sengiF sengiM CAREER CAREER8 TOWNID arear sex w
## <fct> <fct> <fct> <fct> <fct> <fct> <fct> <fct> <dbl> <fct> <fct> <dbl>
## 1 維持… 都是 50至… 專科 本省… 本省… 高、… 軍公教… 1404 宜花… 男性 0.556
## 2 維持… 台灣人 60歲… 大學… 本省… 本省… 高、… 軍公教… 6306 大台… 男性 0.779
## 3 永遠… 都是 30至… 高中… 本省… 本省… 藍領 私部門… 6410 高屏… 男性 1.30
## 4 維持… 台灣人 30至… 高中… 本省… 本省… 高、… 私部門… 101 大台… 男性 1.52
## 5 維持… 都是 30至… 大學… 本省… 本省… 中低… 私部門… 904 雲嘉… 男性 0.626
## # ℹ 2,053 more rows
## [1] "tbl_df" "tbl" "data.frame"
## [1] "factor"
那麼,tibble的用處是什麼?tibble 來自於Hadley Wickham 發展的簡潔數據(tidy dataset)概念,簡潔數據的目標是讓每一個變數都有一個欄位(每一欄都是一個變數),而且每一筆觀察值都有一列,而且每一個值都有一儲存格(也就是每一個儲存格只有一個值,沒有例如\(a/b\)是由兩個值所構成)。詳見Garrett Grolemund & Hadley Wicham (http://r4ds.had.co.nz/index.html)。 tidy dataset也希望資料在同一個表,而非來自於不同的表。
雖然以下的指令適用於資料框以及整潔數據,但是整潔數據方便大數據分析。例如我們想要pp0797b2這筆資料加權之後的性別統計:
## # A tibble: 2 × 2
## sex n
## <fct> <dbl>
## 1 男性 1031.
## 2 女性 1027.
ggplot2
的作者,因此tibble資料適合於ggplot2
的視覺化,例如我們想呈現性別的分佈,不一定用得到tibble:library(ggplot2)
showtext::showtext_auto()
ggplot(tibble_pp0797b2, aes(x=sex)) +
geom_bar(stat='count', fill='steelblue') +
theme(text=element_text(family="HanWangMingBold", size=14))
## # A tibble: 8 × 3
## # Groups: sex [2]
## sex ethnic n
## <fct> <fct> <int>
## 1 男性 台灣人 379
## 2 男性 都是 469
## 3 男性 中國人 63
## 4 男性 無反應 66
## 5 女性 台灣人 377
## 6 女性 都是 574
## 7 女性 中國人 68
## 8 女性 無反應 62
showtext::showtext_auto()
g<-ggplot(df.ethnic, aes(sex, n, fill=ethnic)) +
geom_bar(stat='identity') +
theme(text=element_text(family="HanWangMingBold", size=14))
g
dplyr
的指令可以直覺式地處理資料。dplyr
指令可以產生新的變數,也可以產生統計的結果。首先介紹轉換資料但是不產生統計摘要(例如平均值、最小值、最大值等等)結果的指令。select
這個函數。例如:library(dplyr)
dt <- tibble(
s=c("B", "B", "A","B","A","C", "B", "B","B", "B", "A","B","A","C", "B", "B"),
x = 1:16,
y = 1,
z = x + 2*y,
)
dt %>% select(z, s)
## # A tibble: 16 × 2
## z s
## <dbl> <chr>
## 1 3 B
## 2 4 B
## 3 5 A
## 4 6 B
## 5 7 A
## 6 8 C
## 7 9 B
## 8 10 B
## 9 11 B
## 10 12 B
## 11 13 A
## 12 14 B
## 13 15 A
## 14 16 C
## 15 17 B
## 16 18 B
filter
可以篩選符合條件的變數的觀察值,篩選的變數可以超過一個,例如:## # A tibble: 130 × 24
## Q1 Q2 Q3 Q4 Q5 Q6 Q7 Q8 Q9 Q10 partyid PARTY
## <fct> <fct> <fct> <fct> <fct> <fct> <fct> <fct> <fct> <fct> <fct> <fct>
## 1 非常不同… 非常… 不同… 同意 很難… 不同… 不同… 不相… 不同… 不同… 中立及… 中立…
## 2 非常不同… 非常… 非常… 非常… 同意 非常… 不同… 不相… 不同… 不同… 中立及… 中立…
## 3 非常不同… 同意 不同… 同意 非常… 非常… 同意 非常… 不同… 同意 中立及… 中立…
## 4 非常不同… 很難… 很難… 很難… 不同… 不同… 同意 相信 同意 不同… 民進黨 非常…
## 5 非常同意 非常… 不同… 同意 同意 同意 不同… 非常… 非常… 非常… 國民黨 非常…
## 6 不同意 同意 不同… 同意 同意 同意 同意 不相… 不同… 不同… 國民黨 普通…
## 7 同意 非常… 同意 非常… 不同… 非常… 同意 不相… 同意 非常… 民進黨 非常…
## 8 同意 非常… 非常… 同意 非常… 非常… 同意 非常… 非常… 不同… 中立及… 中立…
## 9 很難說 拒答 同意 拒答 同意 同意 不同… 很難… 很難… 不同… 中立及… 中立…
## 10 同意 同意 不同… 不同… 非常… 同意 同意 不相… 不同… 同意 國民黨 普通…
## # ℹ 120 more rows
## # ℹ 12 more variables: tondu <fct>, ethnic <fct>, age <fct>, edu <fct>,
## # sengiF <fct>, sengiM <fct>, CAREER <fct>, CAREER8 <fct>, TOWNID <dbl>,
## # arear <fct>, sex <fct>, w <dbl>
dt_mutate <- mutate(dt, S=as.factor(s), X=x*100)
dt_mutate <- mutate(dt_mutate, sn=as.numeric(S))
dt_mutate
## # A tibble: 16 × 7
## s x y z S X sn
## <chr> <int> <dbl> <dbl> <fct> <dbl> <dbl>
## 1 B 1 1 3 B 100 2
## 2 B 2 1 4 B 200 2
## 3 A 3 1 5 A 300 1
## 4 B 4 1 6 B 400 2
## 5 A 5 1 7 A 500 1
## 6 C 6 1 8 C 600 3
## 7 B 7 1 9 B 700 2
## 8 B 8 1 10 B 800 2
## 9 B 9 1 11 B 900 2
## 10 B 10 1 12 B 1000 2
## 11 A 11 1 13 A 1100 1
## 12 B 12 1 14 B 1200 2
## 13 A 13 1 15 A 1300 1
## 14 C 14 1 16 C 1400 3
## 15 B 15 1 17 B 1500 2
## 16 B 16 1 18 B 1600 2
mutate
改變變數的性質,例如把變數改成數字類型以及重新歸類因素類型的變數:pp.tmp <- pp0797b2 %>% mutate(sex.n = as.numeric(sex)) %>%
mutate(Taiwanese = dplyr::recode_factor(ethnic,
台灣人='台灣人', 都是 = '雙重認同',
中國人 = '雙重認同', .default = NA_character_))
pp.sex <- pp.tmp %>% janitor::tabyl(sex.n) %>%
janitor::adorn_totals()
pp.Taiwanese <- pp.tmp %>% janitor::tabyl(Taiwanese) %>%
janitor::adorn_totals()
## # A tibble: 16 × 4
## s x y z
## <chr> <int> <dbl> <dbl>
## 1 A 13 1 15
## 2 A 11 1 13
## 3 A 5 1 7
## 4 A 3 1 5
## 5 B 16 1 18
## 6 B 15 1 17
## 7 B 12 1 14
## 8 B 10 1 12
## 9 B 9 1 11
## 10 B 8 1 10
## 11 B 7 1 9
## 12 B 4 1 6
## 13 B 2 1 4
## 14 B 1 1 3
## 15 C 14 1 16
## 16 C 6 1 8
## # A tibble: 1 × 1
## `mean(x)`
## <dbl>
## 1 8.5
dplyr
會存成一個tibble資料,所以需要再取出:## # A tibble: 1 × 1
## x.avg
## <dbl>
## 1 8.5
## # A tibble: 1 × 1
## z.avg
## <dbl>
## 1 10.5
summarize
可以計算的統計有:
mean,平均值
median,中位數
sum,總數
min,最小值
max,最大值
n(),個數,也就是資料筆數
n_distinct,類別的個數
-(請見DSC2014tutorial)
-
例如我們想要知道mtcars
這筆資料中cyl的個數、平均數跟類別的數目:
group_by()
這個函數:## # A tibble: 3 × 2
## s `mean(z)`
## <chr> <dbl>
## 1 A 10
## 2 B 10.4
## 3 C 12
na.rm
這個參數為真,去除遺漏值,再進行統計,例如以flights這筆資料為例,根據tailnum也就是班機號碼,彙總計算班機次數以及距離:library(nycflights13)
by_tailnum <- group_by(flights, tailnum)
delay <- summarise(by_tailnum,
count = n(),
dist = mean(distance, na.rm = TRUE))
delay
## # A tibble: 4,044 × 3
## tailnum count dist
## <chr> <int> <dbl>
## 1 D942DN 4 854.
## 2 N0EGMQ 371 676.
## 3 N10156 153 758.
## 4 N102UW 48 536.
## 5 N103US 46 535.
## 6 N104UW 47 535.
## 7 N10575 289 520.
## 8 N105UW 45 525.
## 9 N107US 41 529.
## 10 N108UW 60 534.
## # ℹ 4,034 more rows
## # A tibble: 4,044 × 3
## tailnum count avgdist
## <chr> <int> <dbl>
## 1 D942DN 4 854.
## 2 N0EGMQ 371 676.
## 3 N10156 153 758.
## 4 N102UW 48 536.
## 5 N103US 46 535.
## 6 N104UW 47 535.
## 7 N10575 289 520.
## 8 N105UW 45 525.
## 9 N107US 41 529.
## 10 N108UW 60 534.
## # ℹ 4,034 more rows
dplyr
,進行統計,並且結合資料視覺化。dplyr
提供了許多轉換資料以及彙總計算的功能,而針對資料的轉換,reshape2
套件有很大的幫助。reshape2
也是由
Hadley Wickham所寫,該套件裡最重要的兩個函數便是 melt() 與
dcast(),如同字面上的意思,melt
是熔化的意思,也就是將資料由多變數熔成較少變數且較長的資料,可以想像資料變長;cast
是鑄造的意思,也就是將資料由較少變數鑄造成較多變數且較寬的資料,可以想像資料變短。cast
有分 dcast 與 acast,只差在要輸出的形式是 data.frame 或是
array。(以上文字參考:https://blog.stranity.com.tw/2016/12/12/r語言reshape2套件/
)library(DSC2014Tutorial)
tmp <- ETL_file("cl_info_other.csv")
bank.info = read.table(tmp,
sep=",", stringsAsFactors=F, header=T)
bank.part=mutate(bank.info,
bank_code = as.factor(bank_code),
etl_dt = substr(etl_dt, 1, 7))
bank.part=mutate(bank.part, yearmonth=format(etl_dt, format='%Y-%m'))
## bank_nm yearmonth mortgage_bal
## 1 日商瑞穗實業銀行 2013-11 0.0000e+00
## 2 台北縣淡水第一信用合作社 2013-11 1.6873e+10
## 3 萬泰商業銀行 2013-11 5.6240e+09
## 4 台中市第二信用合作社 2013-11 1.8949e+10
## 5 基隆市第二信用合作社 2013-11 3.7730e+09
## 6 高雄第三信用合作社 2013-11 2.4760e+09
DSC2014Tutorial
套件的說明,請先安裝該套件,並且輸入slides(‘ETL1’)。如果有問題請參考授課大綱。)
library(reshape2)
bank.part$mortgage_bal.new=bank.part$mortgage_bal/10e+9
wtable<-dcast(bank.part, bank_nm ~ yearmonth, value.var=c('mortgage_bal.new'), sum)
wtable[1:6, ]
## bank_nm 2013-11 2013-12 2014-01 2014-04 2014-05
## 1 三信商業銀行 156.5468 7.4360 5.5540 3.7230 1.8631
## 2 上海商業儲蓄銀行 854.4311 45.8736 34.0033 23.7441 11.8944
## 3 中國信託商業銀行 2483.0095 126.2968 90.6653 65.1645 32.7264
## 4 中國國際商業銀行 57.8369 0.0000 0.0000 0.0000 0.0000
## 5 中國輸出入銀行 0.0000 0.0000 0.0000 0.0000 0.0000
## 6 中華開發工業銀行 0.0338 0.0000 0.0000 0.0000 0.0000
colnames(wtable)<-c("bank_nm","time1","time2","time3","time4","time5")
bank.melt=melt(wtable, id.vars=c('bank_nm'))
# For example, renaming "variable" to "new_variable" and "value" to "new_value"
ggplot2
進行視覺化,目標是顯示每一個銀行在五個時間點的貸款總額變化:library(ggplot2)
names(bank.melt)[names(bank.melt) == "Variable"] <- "Date"
#complete
p=ggplot(bank.melt, aes(x = variable, y=value, group=bank_nm, color=bank_nm)) +
geom_line(stat="identity") +
theme(axis.text.x=element_text(family="msjh", size=10)) +
scale_x_discrete(labels = c("2013-11", "2013-12", "2014-01", "2014-04", "2014-05")) +
theme_bw() +
labs(x = "Date")
#-------------------------------------------------
#partial: 3 banks
set.seed(02139)
bankname<-unique(bank.melt$bank_nm)
r<-sample(c(1:length(bankname)), size=3, replace=F)
bankname.r <- bankname[r]
bankname.r
## [1] "永豐商業銀行" "交通銀行" "比利時商富通銀行"
bank.r<-bank.melt[which(bank.melt$bank_nm==bankname.r[1]|
bank.melt$bank_nm==bankname.r[2]|
bank.melt$bank_nm==bankname.r[3]),]
p=ggplot(bank.r, aes(x = variable, y=value, group=bank_nm, color = bank_nm)) +
geom_line(stat = "identity") +
theme(legend.text=element_text(family="微軟正黑體", size=10)) +
scale_x_discrete(labels = c("2013-11", "2013-12", "2014-01", "2014-04", "2014-05")) +
theme_bw() +
labs(x = "Date")
p
可以看出有的銀行一開始貸款總額相當大,然後突然下降,有的則是一直缺少房貸。
接下來我們看另一個範例。還記得介紹迴圈時所示範的清理主計處數據:
library(foreign)
DAT <- here::here("data", "CS3171D1A.csv")
stat.dat <-read.csv(DAT, header=TRUE, sep=";",dec=".", fileEncoding="BIG5")
tempold<-data.frame()
for (i in 1:3){
for (u in 1:23){
tempold[u,i]<-stat.dat[i+1, u+1]
}
print(i)
}
## [1] 1
## [1] 2
## [1] 3
tempunemploy<-data.frame()
for (i in 1:3){
for (u in 1:23){
tempunemploy[u,i]<-stat.dat[i+13, u+1]
}
print(i)
}
## [1] 1
## [1] 2
## [1] 3
countyname<-colnames(stat.dat)[-1]
temp.df <- data.frame(countyname, tempold, tempunemploy)
temp.df.t <-as_tibble(temp.df); temp.df.t
## # A tibble: 23 × 7
## countyname V1 V2 V3 V1.1 V2.1 V3.1
## <chr> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
## 1 臺北縣 6.37 6.44 6.55 3 4.9 5.5
## 2 宜蘭縣 10.2 10.5 10.8 3.6 5 5.4
## 3 桃園縣 7.46 7.49 7.51 2 4.3 5.1
## 4 新竹縣 9.69 9.91 10.2 1.7 3.8 4.4
## 5 苗栗縣 11.0 11.2 11.6 2.7 4.5 4.9
## 6 臺中縣 7.16 7.32 7.5 3.5 5 5.4
## 7 彰化縣 9.42 9.73 10.0 1.7 4 5.2
## 8 南投縣 10.6 10.9 11.2 3.8 4.9 5.3
## 9 雲林縣 11.6 12.0 12.4 2.6 4.1 4.7
## 10 嘉義縣 12.4 12.8 13.1 2.8 4 5.2
## # ℹ 13 more rows
在這個資料框中,V1代表2000年的老年人口,所以它有
這兩個性質,而V1.1代表2000年的失業率,也是有兩個性質,為了區隔這兩個特性,我們再結合一次,這次把失業率放在老年人口比率底下:
info <- rep('old', 23)
temp.df1<-cbind(countyname, info, tempold)
info <- rep('unemploy', 23)
temp.df2<-cbind(countyname, info, tempunemploy)
temp.df<-data.frame(rbind(temp.df1, temp.df2))
melt
指令轉置資料,並且把其中的年度資料轉換為字串資料,以方便後面的分析:new.df<-melt(temp.df, id=c('countyname', 'info'),
variable.name=c("Time"),
measure.vars = c("V1","V2","V3"))
new.df$Year<-c()
new.df$Year[new.df$Time=='V1']<-2000
new.df$Year[new.df$Time=='V2']<-2001
new.df$Year[new.df$Time=='V3']<-2002
new.df$Year<-as.character(new.df$Year)
g1<-ggplot(new.df, aes(x=countyname, y=value, fill=info)) +
geom_bar(stat='identity') +
theme(axis.text.x=element_text(family="HanWangMingBold", size=10)) + coord_flip()
g1
g2<-ggplot(new.df, aes(x=countyname, y=value, fill=Year)) +
geom_bar(stat='identity') +
theme(axis.text.x=element_text(family="微軟正黑體", size=10))
g2 + coord_flip()
g3<-ggplot(new.df, aes(x=countyname, y=value, fill=info)) +
geom_bar(stat='identity') +
facet_wrap( ~ Year) +
theme(axis.text.x=element_text(family="HanWangMingBold", size=6)) +
coord_flip()
g3
請用group_by
,summarise
,mutate
這些指令,計算
請計算
請計算ISLR
裡面
4.用mutate
把
請用readr::read_delim(file, delim = ';', show_col_type = F)
這個語法讀取
請下載nycflights13
這個套件,然後分析flights
這筆資料,並且建立新變數「速度」,公式為距離(distance)除以飛行時間(air_time)乘以60。請問平均速度多少?最高速多少?可以用filter
篩選沒有遺漏值的觀察值,例如:
tibble1 <-tibble(A=c(NA, NA, NA, 100, 200, 600, NA, 100, 0, 200),
B=200,
C=c(rep(300, 5), rep(400, 5)))
tibble1<- tibble1 %>% filter(!is.na(A)) %>%
summarise(sum(A,B,C), mean(C))
請讀取
請統計mtcars
這筆資料中cyl的各類的平均馬力(hp)
以及每加侖可以行駛的英里數(mpg):
請統計flights資料中每年的最後一天的平均出發以及抵達的遲到分鐘。
請從bank.info資料挑出other_cl_bal大於100億的銀行資料,並且列出銀行的名稱。
## 最後更新日期 04/15/2024