title | subtitle | author | job | license | framework | highlighter | hitheme | ext_widgets | widgets | mode | |||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
ETL on R |
Cheng Yu Lin (aha) and Jia Wei Chen (jiawei) |
by-sa |
io2012 |
highlight.js |
tomorrow |
|
|
selfcontained |
從上面新聞
所述,所以我們想要:
--- &twocol
從上面新聞
所述,所以我們想要:
*** =left
- GDP
- 房貸餘額
- 股價
- 新聞
- 地價資訊
--- &twocol
從上面新聞
所述,所以我們想要:
*** =left
- GDP
- 房貸餘額
- 股價
- 新聞
- 地價資訊
*** =right
- 政府公開資料
- 主計處
- 央行
- 新聞
- 紙本報紙
- 電視新聞
- 電子新聞
- 股市
- Yahoo Stock API
--- &vcenter
即便知道資料在哪,可是資料還是如同
一盤散沙
dplyr
可用類似SQL方法
操作data fromexts
處理時間
格式好用的套件gdata
可以處理Excel 2007
以上的文件quantmod
可以處理股市
資料stringr
字串
相關處理
--- .quote
來上課的,有
福
了
DSC2014Tutorial
R社群為了這次Tutorial製作的套件,所有的教材都在這了
deps <- available.packages("http://taiwanrusergroup.github.io/R/src/contrib")[1,"Imports"]
pkgs <- strsplit(gsub("\\s", "", deps), ",")[[1]]
for(i in seq_along(pkgs)) {
# You can change your favorite repository
if (require(pkgs[i], character.only = TRUE)) next
install.packages(pkgs[i], repo = "http://cran.csie.ntu.edu.tw")
}
install.packages('DSC2014Tutorial',
repo = 'http://taiwanrusergroup.github.io/R', type = 'source')
library(DSC2014Tutorial)
安裝之後, 輸入以下指令就可以打開投影片:
slides("ETL")
- 用R整理
結構
化資料 STEP1 房貸餘額1 , STEP2 GDP - 用R整理
非結構化
資料 STEP3新聞分析
- 整併全部的資料 STEP4
--- .dark .segue
請連線到
https://survey.banking.gov.tw/statis/stmain.jsp?sys=100&funid=r100
- 直接到https://raw.githubusercontent.com/ntuaha/TWFS/master/db/cl_info_other.csv下載檔案
- 應該會看見
cl_info_other.csv
- 讀入它!
或是
library(DSC2014Tutorial)
ETL_file("cl_info_other.csv")
至少要記得的 read.table
Cl_info = read.table(file=ETL_file("cl_info_other.csv"),sep=",",stringsAsFactors=F,header=T)
- 輸出形態為
Data Frame
- file 就是指讀入的檔案路徑
- sep 指的是欄位分割用的符號,通常csv檔案格式是透過
,
做分割 - stringsAsFactors 預設是
True
, 會讓讀入的字串都用Factor形態儲存,那麼資料就會轉為整數儲存與額外的對照表 - header 預設是
False
,表示第一行是不是表格標頭,作為輸出的dataframe欄位名的colnames
View(Cl_info)
str(Cl_info)
--- .quote
直接讀入是否覺得怪怪的?
etl_dt
data_dt
是文字
但應該是時間
bank_code
也是文字
但應該是factor
library(DSC2014Tutorial)
library(dplyr)
Cl_info = read.table(file=ETL_file('cl_info_other.csv'),header=T,sep=",",stringsAsFactors=F)
Cl_info_part = mutate(Cl_info,data_dt = as.POSIXct(data_dt),
bank_code = as.factor(bank_code),etl_dt = as.POSIXct(etl_dt))
View(Cl_info_part)
str(Cl_info_part)
> - 到這裡已經完成第一次的資料`Extraction`與`Transformation`了!
--- .quote
看見資料了!但是剛剛處理過程中的
mutate
是什麼?
--- .quote
看見資料了!但是剛剛處理過程中的
mutate
是什麼?
在
R
中用來做__資料清理__與__資料處理__好用的套件dplyr
其中之一的函式
--- .quote
接下來我們將介紹三個基本函式
--- &twocol_dynamic w1:68% w2:28%
*** =left
Cl_demo1 = select(資料表,欄位1,欄位2,欄位3)
第一個參數
為輸入的data frame後續參數
為選取的欄位名稱
### 給熟悉`SQL`的使用者
select data_dt,bank_nm,mortgage_bal from Cl_info;
*** =right
--- &twocol_dynamic w1:68% w2:28%
*** =left
Cl_demo1 = select(Cl_info,data_dt,bank_nm,mortgage_bal)
第一個參數
為輸入的data frame後續參數
為選取的欄位名稱
### 給熟悉`SQL`的使用者
select data_dt,bank_nm,mortgage_bal from Cl_info;
*** =right
--- &twocol_dynamic w1:68% w2:28%
*** =left
Cl_demo2 = filter(Cl_info,mortgage_bal>1000000)
第一個參數
為輸入的data frame第二個參數
為邏輯運算式,可用data frame裡的欄位,當結果為True
時,該筆資料列保留
### 給熟悉`SQL`的使用者 ``` select * from Cl_info where mortgage>1000000; ```
*** =right
--- &twocol_dynamic w1:68% w2:28%
*** =left
Cl_demo3 = mutate(資料表,新欄位名 = 運算式)
第一個參數
為輸入的 data frame第二參數
為計算式,也可以用來當做轉換資料形態,變更欄位為名稱使用
- 例如: bank_code = as.numeric(bank_code)
### 給熟悉`SQL`的使用者
select mortgage_bal/1000000 as mortage from Cl_info;
*** =right
--- &twocol_dynamic w1:68% w2:28%
*** =left
Cl_demo3 = mutate(Cl_info,mortage = mortgage_bal/1000000)
第一個參數
為輸入的 data frame第二參數
為計算式,也可以用來當做轉換資料形態,變更欄位為名稱使用
### 給熟悉`SQL`的使用者
select mmortgage_bal/1000000 as mortage from Cl_info;
*** =right
--- &twocol_dynamic w1:68% w2:28%
*** =left
Cl_demo4 = arrange(資料表,欄位1,desc(欄位2)))
第一個參數
為輸入的 data frame後續參數
為排序用欄位,預設遞增,可以透過desc()
變成遞減排序
### 給熟悉`SQL`的使用者
select * from Cl_info order by mortage,data_dt desc ;
*** =right
--- &twocol_dynamic w1:68% w2:28%
*** =left
Cl_demo4 = arrange(Cl_info,mortgage_bal,desc(data_dt))
- 輸出data frame
第一個參數
為輸入的 data frame後續參數
為排序用欄位,預設遞增,可以透過desc()
變成遞減排序
### 給熟悉`SQL`的使用者
select * from Cl_info order by mortage,data_dt desc ;
*** =right
- 請幫忙從Cl_info_part找出
data_dt
,bank_nm
,mortgage_bal
- 請幫忙從Cl_info_part挑選出
mortgage_bal
大於1千萬的銀行資料 - 請幫忙排序Cl_info_part出
mortgage_bal
由小到大,但資料時間data_dt
從大到小 - 請執行下面程式碼,我們後續會利用
Cl_info_part2
Cl_info_part2 = mutate(Cl_info_part,time= as.POSIXct(data_dt))
--- .dark .segue
--- .quote
讓我們來練習抓下一個資料
GDP
請連線到 http://ebas1.ebas.gov.tw/pxweb/Dialog/NI.asp
- GDP從直接下載
國民生產毛額之處分
- 季(1980之後)
- 選全部的日期
- 選全部的計價方式
- 項目選GDP
- 總類選原始值
- 按繼續後,選從螢幕顯示Excel檔
- 開啟後,另存新檔成csv檔
- 開回
RStudio
開始處理資料
或是ETL_file("GDP.txt")
--- &vcenter
練習讀入與創建一個
GDP
的 data frame
--- .quote
答案
GDP = read.table(file=ETL_file("GDP.txt"),sep=",",stringsAsFactors=F,header=F)
--- .quote
輸入
View(GDP)
觀察GDP
會發現怎麼前後有很多列的資料是不要的
--- &twocol_dynamic w1:38% w2:58%
*** =left
- 去除前後
不相干
的資料列 - 轉換欄位的格式
- 將單位轉換,從
百萬元變成元
- 將不應該出現的
,
去除
- 抽離
年份
與季
*** =right
GDP_part = GDP[5:136,]
colnames(GDP_part) = c("time","GDP","GDP_yoy","GDP_2006","GDP_2006_yoy",
"GDP_minus","GDP_minus_yoy")
rownames(GDP_part) = NULL
View(GDP_part)
另外一個簡單的例子
iris
iris_part <- iris[4:6,]
rownames(iris_part) <- c('a','c','d')
View(iris_part)
# 去除中間不合理的,在數字欄位上與補上百萬
GDP_part2= mutate(GDP_part,GDP = as.numeric(gsub(",", "",GDP))*1000000)
- 我們利用了
gsub
, 替換字元,將原先有問題的,
去除 - 而後利用了
as.numeric
將原來的文字
形態改成數字
GDP_part3 = mutate(GDP_part2,year=as.numeric(substr(time,0,4)),
season=as.numeric(substr(time,6,6)))
GDP_part4 = select(GDP_part3,year,season,GDP)
- 我們利用了
substr
, 取出特定位置的資料 - 再次利用
as.numeric
, 將文字轉成數字
- 去除頭尾不合理的資料列
- 去除GDP的
,
, 然後將它轉成數字 - 將
year
,season
抽離出來並轉成數字,同時最後資料只保留GDP
,year
,season
--- .quote
--- &vcenter
非結構化
的新聞與股市資料!
--- .dark .segue
--- .dark .segue
- 將房貸餘額匯總到
每個月
的資料 - 將GDP匯總到
每年
的資料 - 透過
年份
將房貸餘額與GDP的表結合
起來
--- &twocol_dynamic w1:78% w2:18%
*** =left
Cl_info_part3 = group_by(Cl_info_part2,time) #先匯總
Cl_info_part4 = summarise(Cl_info_part3,
mortage_total_bal = sum(mortgage_bal, na.rm = TRUE))
第一個參數
為輸入的 data frame第二個欄位
之後都是用來group by/summarise 的欄位
select sum(mortgage_bal) as mortage_total_bal
from Cl_info group by time ;
--- &vcenter
group by 可加先下也可不下,不下的情況是直對接
全部
資料做集匯總運算
- 將房貸餘額每個月的值算出來
- 將GDP每年的值算出來
GDP_part5 = filter(summarise(group_by(GDP_part4,year),GDP=sum(GDP)),is.na(year)==F)
可以使用的函數如下所列
- mean 平均值
- sum 加總
- n 計算個數 例如: A B B C 輸出
4
- n_distinct 計算不同物件的個數 例: A B B C 輸出
3
- max, min 最大或最小值
- median 中位數
- first 該群體第一個,可配合
order_by
使用; first(x,order_by=y) - last 該群體最後一個,可配合
order_by
使用; last(x,order_by=y) - nth 該群體的第n個,可配合
order_by
使用; nth(x,10))
eg1 = summarise(group_by(Cl_info_part2,time) ,
mortage_mean_bal = mean(mortgage_bal, na.rm = TRUE))
eg2_1 = filter(Cl_info_part2,mortgage_bal >0)
eg2_2 = summarise(group_by(eg2_1,time),count = n())
eg3_1 = filter(Cl_info_part2,mortgage_bal >0)
eg3_2 = mutate(eg3_1,year = format(time,"%Y"))
eg3_3 = summarise(group_by(eg3_2,year),count = n_distinct(bank_nm))
eg4 = summarise(group_by(Cl_info_part2,time),
val = max(mortgage_bal))
eg5_1 = arrange(Cl_info_part2,time,desc(mortgage_bal))
eg5_2 =summarise(group_by(eg5_1,time),val = first(bank_nm))
eg6_1 = arrange(Cl_info_part2,time,desc(mortgage_bal))
eg6_2 = summarise(group_by(eg6_1,time),
val = nth(bank_nm,2))
--- .segue bg:red
- cbind 用來做
1-1
水平結合 - rbind 用來做 垂直結合
- left_join 用來做
多對多
水平結合 - inner_join 用來做
多對多
水平結合
看得懂在幹嘛嗎?
--- &twocol_dynamic w1:68% w2:28%
*** =left
先建立資料集
x=data.frame(c1 = c(1,1,2,3,4,5,5),
c2 = c('A','B','C','D','E','F','G'))
y=data.frame(c1 = c(1,2,2,3,4,6,6),
c2 = c('A','B','C','D','E','F','G'))
*** =right
--- &twocol_dynamic w1:68% w2:28%
*** =left
先建立資料集
x=data.frame(c1 = c(1,1,2,3,4,5,5),
c2 = c('A','B','C','D','E','F','G'))
y=data.frame(c1 = c(1,2,2,3,4,6,6),
c2 = c('A','B','C','D','E','F','G'))
打入 View(x)
與View(y)
應該會看見
*** =right
透過先前創建的x
與y
,以及交集的鍵值c1
ljxy = left_join(x,y,by="c1") #以X為主
ljyx = left_join(y,x,by="c1") #以Y為主
--- &twocol
*** =left
inner_join(x,y,by="c1")
## c1 c2.x c2.y
## 1 1 A A
## 2 1 B A
## 3 2 C B
## 4 2 C C
## 5 3 D D
## 6 4 E E
*** =right
--- &radio2
- left_join Cl_Info_part4
- semi_join Cl_Info_part4
- left_join GDP_part5
- inner_join GDP_part5
- 其他
*** =image
*** .explanation
因為GDP_part5_所俱有的時間點
較少,用這個當作主鍵是比較好的.
- 將GDP與房貸餘額,透過1月的資訊整理起來
GDP_part6 = select(mutate(GDP_part5 ,
time = as.POSIXct(paste(year,'1','1',sep='-'))),time,GDP)
t1 = left_join(GDP_part6,Cl_info_part4,by="time")
t2 = filter(t1,is.na(mortage_total_bal)==FALSE)
看一下資料 View(t2)
--- .segue bg:indigo
--- &twocol_dynamic w1:18% w2:78%
see1 = filter(mutate(t2,ratio =mortage_total_bal/GDP),is.na(ratio)==FALSE)
*** =left
畫圖
*** =right
library(ggplot2)
ggplot(see1, aes(time, ratio))+geom_smooth(method="loess") +
scale_size_area() +geom_point(aes(size = 20), alpha = 1/2)
--- &twocol_dynamic w1:18% w2:78%
利用解釋
將圖想要表達的意思更清楚地傳達給觀眾
*** =left
- 畫圖
解釋
*** =right
- 09達到高峰,但之後房貸與GDP的比值平穩維持在37.5%
- GDP成長比率與房貸餘額幾乎成正比
- 從新聞顯示
- 09年遺產稅調降, 許多人回來
投資
?炒房
? - 10年開始打房政策
- 如果加上
房價所得比
,還可以說什麼呢?
--- &twocol_dynamic w1:18% w2:78%
將所有的解釋與圖表包裝成一個故事
,展現出來
*** =left
- 畫圖
- 解釋
報告
*** =right
--- .segue bg:orange
--- &twocol_dynamic w1:18% w2:78%
*** =left
- 設定問題
- 下載與讀入與整理
- 整合資料
- 畫圖
- 解釋
- 報告
*** =right
--- .segue bg:green
- 建立R Script
iris
iris_part <- iris[4:6,]
rownames(iris_part) <- c('a','c','d')
write.csv(iris_part,file="[想要的目錄]/GG.csv")
- 儲存到特定位置下 假定叫做Script.R
- 在terminal執行
R CMD BATCH [該檔案儲存位置]/Script.R
- 可透過
crontab
定期執行
- 安裝套件
install.packages("RCurl")
library(RCurl)
- 讀檔案 (非Windows)
DF = read.table(sep=",", header=TRUE,
file= textConnection(
getURL("https://raw.githubusercontent.com/ntuaha/TWFS/master/db/cl_info_other.csv")
))
- 讀檔案 (Windows)
DF = read.csv(sep=",", header=TRUE,
file="https://raw.githubusercontent.com/ntuaha/TWFS/master/db/cl_info_other.csv",
fileEncoding="UTF-8")
--- .segue bg:blue
- 自動化排程
- 與資料庫溝通
- 其他的資料源
- 結構化資料
- 非結構化資料
- 培養對資料的品味