iT邦幫忙

2017 iT 邦幫忙鐵人賽
DAY 8
0
Big Data

資料科學:使用 Clojure系列 第 8

Day 08 - 單元二:推論統計(一)

第二章有第二章自己的 repo: ch2,裡面有一個資料下載腳本,主要是來自於一假想公司 AcmeContent 的影片觀看資料,dwell-time 是網站停留時間長度。

載入、分析資料

上個單元,我們有使用過 incanter.excel/load-xls。這裡將使用 incanter.io/read-dataset 來讀取 tab-seperated file。

(defn load-data [file]
  (-> (io/resource file)
      (io/read-dataset :header true :delim \tab)))

(defn ex-2-1 []
  (-> (load-data "dwell-times.tsv")
      (i/view)))

可以通過 Day 06 介紹的繪圖函數 c/histogram 簡單的看資料分布狀況:

(defn ex-2-2 []
  (-> (i/$ :dwell-time (load-data "dwell-times.tsv"))
      (c/histogram :x-label "Dwell time (s)"
                   :nbins 50)
      (i/view)))

2-2

如圖,這不是一個常態分布。在展示這樣的資料上,將 Y 軸數據取 log 是不錯的方法。很多的數據,例如地震或噪音,其實也都是通過將數值資料取對數的方式來表示。我們可以使用 c/log-axis 這個函數來修正 Y 軸數據。

(defn ex-2-3 []
  (-> (i/$ :dwell-time (load-data "dwell-times.tsv"))
      (c/histogram :x-label "Dwell time (s)"
                   :nbins 20)
      (c/set-axis :y (c/log-axis :label "Log Frequency"))
      (i/view)))

若只有一軸取對數,此圖稱為 log-linear,若 X、Y 軸都取對數,則稱呼為 log-log 圖。通過繪圖可以看到 dwell-time 跟頻率的對數有限性關係。

指數分布(The Exponential Distribution)

首先來看看指數分布的平均值跟標準差。

(defn ex-2-4 []
  (let [dwell-times (->> (load-data "dwell-times.tsv")
                         (i/$ :dwell-time))]
     (println "Mean:   " (s/mean dwell-times))
     (println "Median: " (s/median dwell-times))
     (println "SD:     " (s/sd dwell-times))))

;; Mean:   93.2014074074074 
;; Median: 64.0 
;; SD:     93.96972402519796 

在完美的指數分布中,平均跟標準差會是相同的!另一個指數分布的特色是無記憶性(memoryless),也就是某個狀況下的機率大小(例如:觀眾繼續觀看影片的機率),並不會因為過去的情況變化而有所改變(例如:已經看了多久影片)。以地震的例子,也就是說,即便在過去的兩百年都沒發生地震,明年地震的機率,跟去年有地震發生的明年地震的機率是相等的。

處理時間與日期

若要深入探索資料,勢必要能處理日期、時間相關的資料。在原始資料中,日期、時間是以字串形式儲存,必須先轉換成 Java 的資料結構!這裡使用 clj-time。這個庫允許我們:

  • 在日期、時間混合的字串中除去時間(或日期)clj-time.parse
  • 過濾特定的日期,計算日期屬性,例如是否為星期一、是否為周末等 clj-time.predicates

接著我們就可以建構函數了:

(defn with-parsed-date [data]
  (i/transform-col data :date (comp tc/to-local-date f/parse)))

(defn filter-weekdays [data]
  (i/$where {:date {:$fn p/weekdays?}} data))

(defn mean-dwell-times-by-date [data]
  (i/$rollup :mean :dwelltime :date data))

(defn daily-mean-dwell-times [data]
  (->> (with-parsed-date data)
       (filter-weekdays)
       (mean-dwell-times-by-date)))
  • with-parsed-date:將日期字串轉化為日期資料結構
  • filter-weekdays:輸入一個日期資料結構,輸出一個 true false 列表
  • mean-dwell-times-by-datge:通過列表將為 true 的行取出做比較

計算一下周間的影片觀看狀況:

(defn ex-2-5 []
  (let [means (->> (load-data "dwell-times.tsv")
                   (daily-mean-dwell-times)
                   (i/$ :dwell-time))]
    (println "Mean:   " (s/mean means))
    (println "Median: " (s/median means))    
    (println "SD:     " (s/sd means))))

;; Mean:    90.210428650562 
;; Median:  90.13661202185791 
;; SD:      3.722342905320035 

發現 SD 小了很多。為什麼呢?

(defn ex-2-6 []
  (let [means (->> (load-data "dwell-times.tsv")
                   (daily-mean-dwell-times)
                   (i/$ :dwell-times))]
    (-> (c/histogram means
                     :x-label "Daily mean dwell time (s)"
                     :nbins 20)
        (i/view))))

結果竟然是近似常態分佈的狀況:以 90 秒左右為軸,向左右以標準差 3.7 秒分布。


上一篇
Day 07 - 單元一:描述統計(二)
下一篇
Day 09 - 單元二:推論統計(二)
系列文
資料科學:使用 Clojure30

尚未有邦友留言

立即登入留言