Data wrangling and visualization

I. 緣由

          As title, 隨著處理資料的技能越點越多,基本上在每一次的分析裡不可能只用到一個data table,一定還會伴隨著很多合併(merge)、角力(wrangling)的過程;進行EDA的時候也一定會使用到視覺化的技術,好讓資料看起來能更加的能夠溝通。
          這篇文章會以R for data science為基礎,介紹裡面關於R是如何處理關聯資料集(relational data) 與 資料視覺化(data visualization ) 的相關技巧。
           同時,在我學習python的時候也提醒自己不要忘記R的語法~~~


II. tidy data

      Tidy data 是由 R Studio 之神 Hadley Wickham(不誇張,真的) 所提出,是一種「資料架構標準」,有分析經驗的朋友們都知道,資料角力會花上的時間遠比建模來的多,然而,傳統的方式把資料清理乾淨,有時不一定利於分析,例如Excel的樞紐分析,因此Hadley Wickham題出了以結構化的方式整理資料更有利於後續分析,就是所謂的 tidy data。

        而一個 Tidy Dataset 會滿足以下三個條件(如下圖所示):
  • 每個變數 (variable) 都會形成一個 column
  • 每個觀察個體 (observation) 都會形成一個 row
  • 每一種類型的觀察個體會形成一個 table,比如說:地區特徵跟個體資料應該存成兩個不同的資料表格。
介紹一下幾種常用的功能:
1. gather
head(table4a)
# A tibble: 3 x 3
  country     `1999` `2000`
  <chr>        <int>  <int>
1 Afghanistan    745   2666
2 Brazil       37737  80488
3 China       212258 213766
table4a %>% 
  gather(`1999`, `2000`, key = "year", value = "cases")
# A tibble: 6 x 3
  country     year   cases
  <chr>       <chr>  <int>
1 Afghanistan 1999     745
2 Brazil      1999   37737
3 China       1999  212258
4 Afghanistan 2000    2666
5 Brazil      2000   80488
6 China       2000  213766
1999、2000都是屬於年份,將其tidy後,兩者靠在同一個column了~。


2. spread
table2
# A tibble: 12 x 4
   country       year       type            count
   <chr>          <int>     <chr>           <int>
 1 Afghanistan  1999  cases             745
 2 Afghanistan  1999  population   19987071
 3 Afghanistan  2000  cases            2666
 4 Afghanistan  2000  population   20595360
 table2 %>% 
 spread(key = type, value = count)
# A tibble: 6 x 4
  country      year  cases population
  <chr>       <int>  <int>      <int>
1 Afghanistan  1999    745   19987071
2 Afghanistan  2000   2666   20595360
3 Brazil       1999  37737  172006362
4 Brazil       2000  80488  174504898
5 China        1999 212258 1272915272
6 China        2000 213766 1280428583
spread()則是能把同一個Column內的變數拓展到外面,形成每行一個變數

3. seperate
> table3
# A tibble: 6 x 3
  country          year      rate             
* <chr>            <int>      <chr>            
1 Afghanistan  1999  745/19987071     
2 Afghanistan  2000  2666/20595360    
3 Brazil           1999  37737/172006362  
4 Brazil           2000   80488/174504898  
5 China          1999   212258/1272915272
6 China          2000   213766/1280428583
table3 %>% 
  separate(rate, into = c("cases", "population"), sep = "/")

# A tibble: 6 x 4
  country          year cases  population
  <chr>             <int> <chr>  <chr>     
1 Afghanistan  1999   745    19987071  
2 Afghanistan  2000   2666   20595360  
3 Brazil           1999   37737  172006362 
4 Brazil           2000   80488  174504898 
5 China           1999   212258 1272915272
6 China           2000   213766 1280428583

4. unite

  table5
# A tibble: 6 x 4
  country     century year  rate             
* <chr>       <chr>   <chr> <chr>            
1 Afghanistan 19      99    745/19987071     
2 Afghanistan 20      00    2666/20595360    
3 Brazil      19      99    37737/172006362  
4 Brazil      20      00    80488/174504898  
5 China       19      99    212258/1272915272
6 China       20      00    213766/1280428583

> table5 %>%
+   unite(new, century, year, sep="")
# A tibble: 6 x 3
  country     new   rate             
  <chr>       <chr> <chr>            
1 Afghanistan 1999  745/19987071     
2 Afghanistan 2000  2666/20595360    
3 Brazil      1999  37737/172006362  
4 Brazil      2000  80488/174504898  
5 China       1999  212258/1272915272
6 China       2000  213766/1280428583

一言以蔽之呢~就是
  • gather(): 將「寬」資料變「長」
  • spread(): 將「長」資料變「寬」
  • separate(): 將單一欄位切分成多個欄位
  • unite(): 將多個欄位合併成單一欄位
~簡單清楚明瞭實用~

III. relational data
1. Concept of "key"

     如前言所提,資料分析不會只涉及單一一個資料表,面對多個表格,必須將他們結合起來,用來連接每對資料表的變數,我們便稱為他的鍵(Key)。
鍵值又分為兩種

(a) 主鍵(primary key)
唯一識別自己資料表(在這裡假設為A)中的一個觀察變數(X),能夠識別資料裡所有的個案

(b) 外鍵(foreign key)
用來其他資料表的鍵,我們稱為外鍵

2. Join
在這裡以簡單的例子說明join的整理與功能
x <- tribble(
  ~key, ~val_x,
  1, "x1",
  2, "x2",
  3, "x3"
)
y <- tribble(
  ~key, ~val_y,
  1, "y1",
  2, "y2",
  4, "y3"
)
> x
# A tibble: 3 x 2
    key val_x
  <dbl> <chr>
1     1     x1   
2     2     x2   
3     3     x3   
> y
# A tibble: 3 x 2
    key val_y
  <dbl> <chr>
1     1      y1   
2     2      y2   
3     4      y3 
我們可以看到對x而言,key即為主鍵,y的key為x的外鍵


(a) inner_join
x %>% 
  inner_join(y, by = "key")
 key val_x val_y
  <dbl> <chr> <chr>
1     1    x1    y1   
2     2    x2    y2   
x且y都具備的key為1, 2,因此inner_join後顯示的即為1/2兩個key


(b) left_join
> x %>% 
+   left_join(y, by = "key")
# A tibble: 3 x 3
    key val_x val_y
  <dbl> <chr> <chr>
1     1 x1    y1   
2     2 x2    y2   
3     3 x3    NA  
left_join保留了x的key

(c) right_join
 x %>% 
+   right_join(y, by = "key")
# A tibble: 3 x 3
    key val_x val_y
  <dbl> <chr> <chr>
1     1 x1    y1   
2     2 x2    y2   
3     4 NA    y3   
保留y

(d) full_join
 x %>% 
+   full_join(y, by = "key")
# A tibble: 4 x 3
    key val_x val_y
  <dbl> <chr> <chr>
1     1 x1    y1   
2     2 x2    y2   
3     3 x3    NA   
4     4 NA    y3   
通通保留~~~~

相關圖片

其實不用硬記,看看這張圖什麼都能一目了然了呢~



3. compare with SQL and merge function

了解join的功能後,別忘了R也有merge的功能,兩者的功用差不多,最多是在語法上做調整
可以參考下列表格~

dplyrmerge
inner_join(x, y)merge(x, y)
left_join(x, y)merge(x, y, all.x = TRUE)
right_join(x, y)merge(x, y, all.y = TRUE),
full_join(x, y)merge(x, y, all.x = TRUE, all.y = TRUE)

其實很多程式的語法都會想盡辦法和SQL有直接關連(畢竟是最普遍的資料庫系統),以下整理出語法的比較:

dplyrSQL
inner_join(x, y, by = "z")SELECT * FROM x INNER JOIN y USING (z)
left_join(x, y, by = "z")SELECT * FROM x LEFT OUTER JOIN y USING (z)
right_join(x, y, by = "z")SELECT * FROM x RIGHT OUTER JOIN y USING (z)
full_join(x, y, by = "z")SELECT * FROM x FULL OUTER JOIN y USING (z)


IV. visualization with ggplot2

R語言擁有強大的視覺化工具,ggplot2套件,以下會簡單介紹詳細的使用語法,ggplot2現在也已經被包含在萬用package tidyverse裡,因此我們只需要安裝 tidyverse package即可使用,再次感謝大神 Hadly Wickham~~~~~

ggplot(data = <DATA>,aes(x= , y=)) + 
  <GEOM_FUNCTION>(
     stat = <STAT>, 
     position = <POSITION>
  ) +
  <COORDINATE_FUNCTION> +
  <FACET_FUNCTION>
以上是ggplot完整作畫的基礎步驟,
(1)決定資料集,變數
(2)選擇geom_function: 例如geom_histogram、geom_bar、geom_jitter
可以多重stack上去,取決於圖需要多少元素向閱覽者溝通
(3)coord_funciton: coord_flip()橫向翻轉;coord_polar() 南丁格爾玫瑰圖
(4) facet_function : facet_grid

大致上的文法架構已經明瞭後,剩下的就是不斷練習,並且經驗各個geom function專有的規矩和調整,很複雜,pratice makes perfect 是永遠不變的道理!


以下,讓我們一起來探討ggplot畫圖功能的強大吧~


ggplot(full[1:891,], aes(Age,fill = factor(Survived)))+
  geom_histogram(bins = 40)+
  theme_few()+
  xlab("Age")+
  scale_fill_discrete(name = "Survived")+
  ggtitle("Age / Survived")

     



ggplot(full[1:891,], aes(Sex,fill = factor(Survived)))+
  geom_bar(stat = "count",position = "dodge")+
  theme_bw()+
  xlab("sex")+
  ylab("count")+
  scale_fill_discrete(name = "survived")+
  ggtitle("Sex / Survived")

ggplot 將資料集以及變數指定完成,再加上geom_histogram決定要劃長條圖,
而同樣是histogram, 只需要在position 的地方加上dodge,就可以將不同類別錯開。


ggplot(full[1:891,], aes(Age, fill = factor(Survived))) + 
  geom_histogram(bin = 30)+
  theme_few()+
  xlab("Age")+
  ylab("count")+
  facet_grid(.~Sex)+
  scale_fill_discrete(name = "survived")+
  theme_few()+
  ggtitle("Age/Sex/Survived")


類似的語法,加上facet_grid(.~Sex)+
就能夠以Sex為分類將兩種性別分開



ggplot(data,aes(x=displ, y = hwy))+geom_point(aes(color=class))+
geom_smooth(data=filter(mpg,class=="subcompact"),se=FALSE)
也可以將兩種geom畫在一起,可以更加促進圖表的溝通能力


V. shiny 與 plotly的視覺畫呈現*

雖然有了強大的ggplot函數,R現在有shiny與plotly的實作功能圖表溝同能力無限up

library(plotly)
g<-ggplot(data,aes(x=displ, y = hwy))+geom_point(aes(color=class))+
geom_smooth(data=filter(mpg,class=="subcompact"),se=FALSE)

ggplotly(g)




透過ggplotly()函數,我們更可以了解到每一筆資料的詳細情況了!!!



本篇簡易的介紹了資料角力常用技巧以及R常用的畫圖技巧
有任何意見想討論都可以直接於下方留言唷~~~~~



留言

這個網誌中的熱門文章

Word Vector & Word embedding 初探 - with n-Gram & GLOVE Model

文字探勘之關鍵字萃取 : TF-IDF , text-rank , RAKE

多元迴歸分析- subsets and shrinkage