跳到主要內容

使用python繪製視覺化--樹狀圖(Treemap)



樹狀圖在某些特點上跟泡泡圖的類似,都可以提供不只1個維度的資訊,並透過形狀大小、顏色來呈現。但是比較不同的地方是樹狀圖有層級的概念,可以用來呈現階層式資料。例如將全臺灣當作第一層,縣市當做第二層(分支),再下一層則是縣市人口年齡組成。

在這基本概念下利用pythonPlotly套件來繪製堆疊區域圖。這次以2013-2016國民營養健康調查報告書中的數據為例。

以下針對2013-2016國民營養健康調查做簡單的介紹:
²  目的隨時代改變人們飲食習慣也隨之改變,為了對國人的營養健康狀況有所了解,從1980年開始委託衛生署食品衛生處、衛生署食品藥物管理局定期辦理全國性營養健康調查,2013年起改由衛生福利部國民健康署定期辦理。2013-2016年的調查為第五次的國民營養調查。
²  調查對象所有居住在臺灣本島及澎湖設有戶籍的人口,依據縣市人口比例分層集束抽樣,進行家戶田野調查。
²  問卷除人口社經等基本資料的收集外,包含24小時飲食回顧、飲食頻率、疾病史、營養知識態度與行為、活動量等相關問卷以及身體健康檢查資料。

2013-2016年總計問卷完訪人數有11,072人,體檢人數為9746人。
十大死因中心血管疾病常常榜上有名,可見一直是國人重要的死亡原因之一,但因疾病病徵較不明顯,相較於癌症來說反而容易受到忽略,但實則不可輕忽,應即早預防與控制,其中抽煙、高血壓、糖尿病、高血脂等都是心血管疾病的危險因子,本次以高膽固醇數據做示範,了解2013-2015年不同年齡層高膽固醇盛行的情況。


操作步驟
1.選定主題,準備素材
2013-2016國民營養健康調查中高膽固醇盛行率為例(衛生福利部國民健康署公告的資料),了解不同年齡層收到的檢體中,高膽固醇盛行的形況。開始執行前,尚未安裝plotly者需要先安裝幾個套件plotlynumpy以及squarify,在Window環境下,開起命令提示字元,輸入pip install plotly,其他套件也以相同的方式匯入,安裝完成後,就可進入繪圖步驟。
Squarify這個套件來計算圖形區域的分割,一個大正方形的區域依照比例分割成幾個不同大小的矩形,並運算每個放入的矩形的長寬比需盡量接近1(正方形),當矩形長寬比違反這個情況時,會調整矩行放入的位置至最適情況。

2.確認繪圖需要用到的參數:
因為目前plotly的繪圖沒有辦法像tableau那麼方便,如果要到2層的樹狀結構圖(treemap),就必須藉由半手動的方式達成,第一層變量為年齡分層的採檢人數,方塊的大小由檢體採檢人數多寡決定,這部份可由套件直接計算,第二層為年齡分層的盛行率,盛行率高低的由顏色深淺表示,這部份就只能夠過手動設定調整。
3.繪製樹狀圖treemap
這次採用各分層在同一圖層做建構,省去合併處理的語法。


  1. import plotly.plotly as py
  2. import plotly.graph_objs as go
  3. import numpy as np
  4. import squarify
  5.  
  6. #設定x,y軸的起始值
  7. x = 0.
  8. y = 0.
  9. #設定圖的大小
  10. width = 100.
  11. height = 100.
  12.  
  13. normed = squarify.normalize_sizes(df["pop"], width, height) #df["pop"]為帶入的數據
  14. rects = squarify.squarify(normed, x, y, width, height)
  15.  
  16. color_brewer=df["color"].tolist() #色彩於讀入的表格中已設好,將之轉為串列
  17. z=np.random.randint(4, 30, size=20) #設定色標的範圍
  18. colorscale=[[0.0, 'rgb(169,233,207)'], [0.5, 'rgb(81,211,158)'],[1.0, 'rgb(37,147,102)']] #設定色標的色彩
  19. shapes = []
  20. annotations = []
  21. counter = 0
  22.  
  23. for r in rects:
  24. shapes.append(
  25. dict(
  26. type = 'rect',
  27. x0 = r['x'],
  28. y0 = r['y'],
  29. x1 = r['x']+r['dx'],
  30. y1 = r['y']+r['dy'],
  31. line = dict( width = 1, color="white"), #設定treemap框線的粗細及色彩
  32. fillcolor = color_brewer[counter], #設定填入的色彩
  33. )
  34. )
  35. annotations.append(
  36. dict(
  37. x = r['x']+(r['dx']/2),
  38. y = r['y']+(r['dy']/2),
  39. text = "年齡"+df["age"][counter]+"\n"+"人數:"+str(value[counter])+"\n"+"盛行率:"+str(df["value"][counter])+"%", #設定框內文字敘述
  40. font=dict(color="black",size=14,family='微軟正黑體'), #設定框內字體及大小
  41. showarrow = False))
  42. counter = counter + 1
  43. if counter >= len(color_brewer):
  44. counter = 0
  45. print(shapes)
  46. # For hover text
  47. trace0 = go.Scatter(
  48. x = [ r['x']+(r['dx']/2) for r in rects],
  49. y = [ r['y']+(r['dy']/2) for r in rects],
  50. text = [ str(v) for v in value],
  51. mode = 'markers',
  52. marker=dict(color=z,colorscale=colorscale, size=14, colorbar=dict(thickness=20)) #將已設定好的色標參數帶入
  53. )
  54.  
  55. layout = dict(
  56. height=700,
  57. width=700,
  58. xaxis=dict(showgrid=False,zeroline=False,showticklabels=False),
  59. yaxis=dict(showgrid=False,zeroline=False,showticklabels=False),
  60. shapes=shapes,
  61. annotations=annotations,
  62. hovermode='closest'
  63. )
  64.  
  65. figure = dict(data=[trace0], layout=layout)
  66.  
  67. py.iplot(figure, filename='squarify-treemap')
  68.  

留言

  1. 您好,謝謝您慷慨地分享統計相關資訊。
    因剛入門統計與程式語言,有很多不了解的地方,不知道是不是能向您請教呢?
    謝謝您喔!

    回覆刪除

張貼留言

這個網誌中的熱門文章

如何快速註冊統合分析題目~以PROSPERO為例

初步檢索心中的愛 當心目中有一個理想題目時,為避免地球上另一個人也同時跟你想的一樣,而且還比我們早發表,若等我們發表時才發現,當下一定很扼腕,有了註冊系統除了幫自己先占好位子,也可以同時確認這個題目是否已經有人正在做了,不用浪費時間投注在上面。很多人其實不曉得實際上到底要如何註冊,以下一起註冊吧。 什麼是 PROSPERO??   PROSPERO (International prospective register of systematic reviews) 是一個國際前瞻性系統性文獻回顧評價系統,由美國國立衛生研究院 NIHR ( National Institute for Health Research )資助,由英國約克大學 CRD(Centre of Reviews and Dissemination) 創立,針對將已完成的評價或正進行中的計畫做紀錄。 目的:避免重複並減少報告偏見的機會,增加透明性。                 步驟流程 Step 1 :檢索主題 先確認其他人是否對這主題感興趣,有人捷足先登了嗎 ?? 也可以確認目前流行的趨勢是哪類型的研究等。 Step 2 :註冊帳號 ID 先到 PROSPERO 官網 ,填寫基本資料後註冊 ID 。 Step 3 :點選註冊文獻 review 要需先有帳號後才能註冊題目,進入頁面後依指示一步一步操作。 以下是網頁步驟,依研究對象是人群還是動物選擇按鈕點選,一般我們都是人群研究,選紫色。同時須確認以下五步驟是否都經過檢驗了。 第 1 步 檢查納入標準。 第 2 步 確保您的 protocol 處於(接近)最終形式。 第 3 步 搜尋 PROSPERO ,以確保評論尚未被註冊。 第 4 步 搜尋 PROSPERO ,以確保您沒有不必要地重複由另一個團隊進行的審核或先前已註冊的審核 第 5 步 開始註冊 Step 4 :點選相關事前準備工作進度。 這裡有一系列問題須皆回答完,才能進行下一步...

python與SAS資料處理-歸人與排除重複

  歸人顧名思義就是將一個人多筆的資料整合,每人只留下 1 筆。   通常取得的資料都是原始資料,並未經過整理。例如手上有疑份顧客購物紀錄,裡面有每個顧客在這 1 年內的每筆消費紀錄,這是一份以每次消費紀錄為 1 筆的紀錄形式,所以一個人可以有多筆的消費紀錄。當我們想要知道這些消費紀錄源自於多少顧客的購買時,這時候就需要用到歸人的概念,將資料轉換為每一個人只有 1 筆資料的紀錄形式 ( 如下圖所示 ) 。 以 SAS 進行資料歸人 歸人留 1 筆消費紀錄 proc sort data =cost; by ID time; run ; /* 在規筆前依照 ID 跟消費日期做排序 */ data cost_1; set cost; by ID; if first.id; run ;   /* 保留第一筆資料 */   之前已經有針對 proc sort 的排序語法進行說明,有需要可參考這篇 文章 , SAS 排序的設定值為升冪,也就是說每個人都會從最早那次的紀錄開始往後排序,所以用 first.id 就可以留下每個人最早那次的消費紀錄。 這邊也可以用排除重複的概念保留 1 筆資料 proc sort data =cost out =cost_2 nodupkey ; BY ID; run ; 利用 nodupkey ,將 ID 重複的資料刪除,僅保留每個 ID 第一次出現的該筆紀錄。   歸人累計所有消費金額 proc sort data =cost; by ID time; run ; data cost_1; set cost; by ID; if first.id then count= 0 ;/* 每個人第一筆資料都令 count=0*/ count+NT;/* 同 ID 累計 NT 數值 */ if last.id; run ;   除了要歸人以外,還要累計每個仁所有的消費金額,所以這邊就會創建一個 count 欄位,每一個人的第一筆 ID 令 count=0 ,在同樣 ID 時累加 NT 的數值,最後每個人保留最後一筆 ID ,也就是最後累計的總額。 以 Python 進行資料歸人...

python與SAS資料處理入門--資料匯入匯出

為什麼要學程式語言,不能用 excel 做大型資料的處理 不建議使用 excel 做大型資料處理的原因有 2 點, (1)excel 行列的限制, 2003 年以前的版本,最大資料列筆數為 65,536 行、欄位數最多為 256 列, 2007 之後的版本雖然行列都有擴展,最大資料列筆數可達到 1,048,576, 行、欄位數最多為 16,384 列,但對於現在隨便動輒幾億筆的資料來說,這真的不算什麼,因此實務上可能會遇到一份資料得分成好幾個 sheet 儲存的情況。 (2) 資料量太大,可能會遇到 excel 執行上耗時的問題。 對於即將跨入大數據的人而言, SPSS 雖然也是個不錯的選項,具有操作簡單之優勢,短期內可快速掌握,但也因介面以選單式操作為主,使用彈性相對受限,此外對於大數據處理效率也較差,如果 未來工作上需經常面對大數據 ( 例如 : 醫學資料庫、商業資料庫 ) ,建議可以直接選擇學習 SAS 、 R 或是 Python 。 以下就挑選 SAS( 付費軟體 ) 以及近年很熱門的 Python( 開源軟體 ) ,從基本的資料匯入、匯出開始介紹起。不論 SAS 或是 Python 皆可以匯入許多不同類型的檔案格式,本文就挑選幾個可能比較常接觸到的類型做說明。 以 SAS 進行操作 介面 執行 SAS 會經常使用到的視窗有幾個部分,以下簡述其用途 : (1) 編輯器:指令輸入,未來相關語法的編輯都在該視窗完成。 (2) 日誌:顯示指令執行結果,如果有程式上的執行錯誤,皆顯示於該視窗。 (3) 結果:分析結果的索引,方便使用者管理結果的部分。 (4) 檔案總管:資料集的管理,可於此處點選瀏覽資料內容。 資料匯入 (proc import) ²      Excel 檔案匯入 proc import datafile = "c:\test.xlsx" /* 資料匯入的路徑 */ out =test  /* 資料匯入後的名稱 */ dbms =xlsx replace; /* 輸入檔案的類型 */ sheet = " Sheet" ; /* 選擇讀取的工作表 */ getnames =YES; /* 第一...