圓餅圖太多項目很雜亂怎麼辦?
用Matplotlib實作帶堆疊長條圖的圓餅圖

8
<h1>&nbsp;</h1><p>我們在<a href="https://factsviz.tw/article/pie-chart-design-trap">「圓餅圖的陷阱和替代圖表:教你如何正確製作圓餅圖」</a>中提到,若項目個數過多,容易導致許多低占比的項目擠在一起,降低辨識度削弱呈現效果。因此我們可以將低占比項目組合成「其他項」,並用堆疊長條圖另外呈現,這麼做可以在提供所有資訊之餘,不模糊焦點。</p><h4>圓餅圖</h4><p>我們先製作一個簡單的圓餅圖。</p><p><img src="/imagefiles/python-matplotlib-piechart-stackbarchart-1.png"></p><pre><code class="language-python">import numpy as np import matplotlib.pyplot as plt data=[1,2,3] fig, ax=plt.subplots(figsize=(8,5)) #建立畫布figure和axes #有三種設定顏色的方法 #https://matplotlib.org/stable/gallery/color/named_colors.html#css-colors #colors=['lightsteelblue','cornflowerblue','royalblue'] #colors=[[0.1, 0.2, 0.5, 0.4],[0.1, 0.2, 0.5, 0.6],[0.1, 0.2, 0.5, 0.8]] colors = plt.get_cmap('Blues')(np.linspace(0.2, 0.7, len(data))) #pctdistance:百分比標籤在切片外的話需&gt;1 #labeldistance:Label在切片內的話需&lt;1 ax.pie(data, labels=data, autopct="%1.2f%%", colors=colors, pctdistance=1.3, labeldistance=.5, startangle=90, #從x軸往逆時針90度 explode=(0.05,0.05,0.05)) #各切片往外移動的距離 plt.show() </code></pre><p>&nbsp;</p><h4>帶堆疊長條圖的圓餅圖</h4><p>堆疊長條圖不僅可以用來呈現「其他項」中各個低占比項目,也可以用在圓餅圖切片延伸的項目上。在範例中,我們用圓餅圖呈現大家對三個選項的同意票數比例,並用堆疊長條圖顯示其中一個選項的同意票年齡分佈。</p><p><img src="/imagefiles/python-matplotlib-piechart-stackbarchart-2.png"></p><pre><code class="language-python">import numpy as np import matplotlib.pyplot as plt from matplotlib.patches import ConnectionPatch fig, (ax1, ax2)=plt.subplots(1,2, figsize=(8,5)) #建立兩個子圖 fig.subplots_adjust(wspace=0) #調整圖之間的距離(將內間距設為0,拉近距離) data=[50,30,100] #把要製成堆積長條圖的項目放在第一個 #切片會從第一個資料開始逆時針排列 angle=-180*(data[0]/sum(data)) #讓要製成堆疊長條圖的該切片置於中間 pie_colors=['cornflowerblue','lightsteelblue','royalblue'] #ax.pie會回傳patched, label text, value text,這裡只需第一個 #(不需要的返回值以底線代替,此處有多個值不被需要,在底線前方加上星號) #startangle為第一個切片開始的角度(以x軸為0逆時針加) #explode為各切片往外移動的距離 wedges,*_=ax1.pie(data, labels=data,autopct="%1.2f%%", colors=pie_colors, startangle=angle, explode=[0.1,0,0]) #堆疊長條圖 age_data=[13,2,20,15] age_ratio=[x/sum(age_data) for x in age_data] age_label=['under 21', '21-40', '41-60', 'over 61'] bottom = 1 #一開始從畫布最上面開始往下畫(第一個長條的Y座標為(0,1)) width = .2 #長條的寬度 #enumerate:(index, vale);zip打包成tuple、*zip解壓;reversed反轉順序,讓堆疊由下往上 for i, (height, label) in enumerate(reversed([*zip(age_ratio, age_label)])): #x座標皆為0;每個長條長度(height)為占比、寬度為width;y座標從第一個長條的1(最上方)-該長條長度開始, #一直往下減去各長條的占比(長度);label為各長條的標籤;alpha為顏色不透明度,index越高的長條越不透明 bottom -= height bc = ax2.bar(0, height, width, bottom=bottom, color=pie_colors[0], label=label, alpha=0.1 + 0.25 * i) ax2.bar_label(bc, labels=[f"{height:.0%}"], label_type='center') #以增加註釋的方式加上文字標籤,置於每個長條的中間;xy為註釋箭頭所指的點, #此例無箭頭因此無顯示;xytext為文字的座標位置 ax2.annotate(label, xy=(0.2,1) ,xytext=(0.2, bottom+(height/2))) ax2.set_title('age of approvers') #設定標題 ax2.axis('off') #移除軸線 ax2.set_xlim(-2.5*width, 2.5*width) #設定x軸範圍,連動bar寬度,讓圖變窄 #連接線 #theta1:該切片右邊角的點(起點);theta2: 左邊角的點(終點) theta1, theta2=wedges[0].theta1, wedges[0].theta2 #center: 該切片中心點(因有explode所以跟其他切片中心點(0,0)不同);r:半徑(1) center, r=wedges[0].center, wedges[0].r bar_height=sum(age_ratio) #長條圖的總長度 #上面的連接線 #2pi弧度=360角度,pi弧度=180度;theta2約為50(x軸為0逆時針50度) #np.pi/180=1角度為多少弧度;np.pi/180*theta2=該切片以圓心畫一個直角三角形,對著圓弧的弧度 #用r*np.cos計算出直角三角形的最短邊長度(在x軸上) x = r * np.cos(np.pi / 180 * theta2) + center[0] y = r * np.sin(np.pi / 180 * theta2) + center[1] #計算直角三角形中平行y軸的邊的長度 #xyA為長條圖左上角;xyB為圓餅圖該切片最上面的點;ax.transData表示資料座標系統 con = ConnectionPatch(xyA=(-width / 2, bar_height), coordsA=ax2.transData, xyB=(x, y), coordsB=ax1.transData) con.set_color(pie_colors[0]) #連接線顏色;或使用rgba,例如(0,0,1,0.5) con.set_linewidth(1) #連接線寬度 ax2.add_artist(con) #加上連接線 #下面的連接線 x = r * np.cos(np.pi / 180 * theta1) + center[0] y = r * np.sin(np.pi / 180 * theta1) + center[1] #xyA為長條圖左下角,xyB為圓餅圖該切片最下面的點 con = ConnectionPatch(xyA=(-width / 2, 0), coordsA=ax2.transData, xyB=(x, y), coordsB=ax1.transData) con.set_color(pie_colors[0]) #連接線顏色;或使用rgba,例如(0,0,1,0.5) con.set_linewidth(1) #連接線寬度 ax2.add_artist(con) #加上連接線 plt.show() </code></pre><p>&nbsp;</p><h4><strong>參考資料</strong></h4><p><a href="https://matplotlib.org/stable/gallery/pie_and_polar_charts/pie_features.html">圓餅圖官方文件</a></p><p><a href="https://matplotlib.org/stable/gallery/pie_and_polar_charts/bar_of_pie.html">圓餅圖+堆疊長條圖官方文件</a>&nbsp;</p>

你可能有興趣

查看目錄
回到頁首