帕累托分析法是基於帕累托法則的一種分析法。
先來說說什么是帕累托法則,其原型是19世紀意大利經濟學家帕累托所創的庫存理論。帕累托運用大量的統計資料分析當時的一些社會現象,概括出一種關鍵的少數和次要的多數的理論,並根據統計數字畫成排列圖,后人把它稱為帕累托曲線圖。簡單的說,帕累托法則其實就是我們常說的二八法則,在經濟學定律中說的是80%的財富掌握在20%的人手中,而在運營中說的則是80%的貢獻度來自於20%的用戶。
而基於帕累托法則的帕累托分析法(Pareto Analysis)是制定決策的統計方法,用於從眾多任務中選擇有限數量的任務以取得顯著的整體效果。
下圖是我基於Pandas隨機模擬出的一組產品數據,並結合Matplotlib來展現這組數據的相關帕累托曲線圖。
如圖可見,藍色的條形柱狀圖代表了每款產品的銷售金額,每一個橘色百分點標記代表了從左往右的銷售累計占比。其中紅色的垂直虛線則是一條數據占>=80%的分界線,也就代表了這條分界線之前的7款產品(即,'G7', 'MX3', 'R9Plus' , 'A37', 'Note5', 'X5Pro', 'A50')占到了總銷售額中83.91%的銷售份額,之后其余的3款產品占比只有16.09%。假如放到現實場景中,就可以根據市場情況制定某些決策,如是否要撤銷某些產品的研發。
接下來為了更好的理解代碼是如何實現的,我將分解代碼成若干段來說說明。首先我用Pandas模擬10組虛擬產品數據。
import numpy as np import pandas as pd import matplotlib.pyplot as plt %matplotlib inline %config InlineBackend.figure_format = 'retina' # 創建模擬數據,10個品類產品的銷售額 data = pd.Series(np.random.randn(10)*500+1000, index=['A37','A50','R7S','Note5', 'G7','R9_Plus','5C','X5_Pro', 'MX3','M5']) print(data)
通過輸出data變量值查看如下,左側的index是我們虛擬的10組產品名稱,而右側對應的數值則是通過random.randn隨機產生的10組基於標准正態分布的偽數據。
A37 1784.729567 A50 198.971079 R7S 985.258417 Note5 1348.619119 G7 1330.237773 R9_Plus 188.307306 5C 2105.157302 X5_Pro 1225.447782 MX3 957.038300 M5 1346.797999 dtype: float64
接着,我們將所有的數據從大到小降序排列並以此構建柱狀圖。
其中要注意的一點是,為什么需要降序排列呢?因為考慮到我們要制作的是累計占比,同樣是計算累計相加值滿足>=80%,從小到大升序排列 與 從大到小降序排列 相比 降序排列能以更少的數據個數預先滿足累計相加值>=80%,也就能體現帕累托法則的二八法則,少數掌握多數的原理。
# 將數值按照從大到小排序 data.sort_values(ascending=False, inplace=True) # 構建畫布 plt.figure(figsize=(10,6)) # 先構建一個從大到小排列的,標准柱狀圖。 data.plot(kind='bar', colormap='GnBu_r', width=0.6, edgecolor='black', rot=0) plt.xlim(-1,11) plt.ylim(0,2000) plt.xlabel('產品名') plt.ylabel('銷售金額') plt.title('銷售情況') plt.legend(['銷售金額'], loc='upper right')
輸出圖如下:
之后,需要繪制另一條累計占比的百分比圖。首先需要通過cumsum函數得到每個產品時的當前累計值,並用這個累計值去除以總銷售金額得到的就是該產品當前的累計占比的百分比數值。得到每個產品當前的累計占比的百分比數值后就可以通過布爾索引篩選出>=80%的產品名稱。有了這個產品名稱就可以獲得該產品的索引位置編號,而這個索引位置十分重要,因為這有助於我們之后用來標注那條紅色分界線的具體位置。
# 累加值 除以 總數值 得到每個階段累加值的占比值。 proportion = data.cumsum() / data.sum() # 用布爾索引列出大於等於0.8的數值列表,而列表里第一行就是大於80%的關鍵點,我們取得它的索引名稱。 key = proportion[proportion >= 0.8].index[0] # 根據之前得到的索引名稱,就可以從data數據中得到該名稱的索引位置。 key_number = data.index.tolist().index(key) proportion.plot(style='--ko', secondary_y=True, color='#FFA500') plt.axvline(key_number, linestyle='--', color='red') for x, y, s in zip(range(len(data)), proportion.values, proportion): if x == key_number: plt.text(key_num+0.2, y-0.035, '累計占比為 {:.2%}'.format(s), color='red', fontsize=12) else: plt.text(x+0.3, y-0.035, "{:.2%}".format(s), fontsize=12, horizontalalignment='center', color='black') plt.ylabel('銷售(比例)') plt.legend(['累積占比'], loc='upper center')
之后將兩段代碼合並,也就是兩張圖合並為一張圖就形成了我們一開始提到的帕累托曲線圖。
最后放上完整代碼如下:
import numpy as np import pandas as pd import matplotlib.pyplot as plt %matplotlib inline %config InlineBackend.figure_format = 'retina' # 創建模擬數據,10個品類產品的銷售額 data = pd.Series(np.random.randn(10)*500+1000, index=['A37','A50','R7S','Note5', 'G7','R9_Plus','5C','X5_Pro', 'MX3','M5']) # 將數值按照從大到小排序 data.sort_values(ascending=False, inplace=True) # 構建畫布 plt.figure(figsize=(10,6)) # 先構建一個從大到小排列的,標准柱狀圖。 data.plot(kind='bar', colormap='GnBu_r', width=0.6, edgecolor='black', rot=0) plt.xlim(-1,11) plt.ylim(0,2000) plt.xlabel('產品名') plt.ylabel('銷售金額') plt.title('銷售情況') plt.legend(['銷售金額'], loc='upper right') # 累加值 除以 總數值 得到每個階段累加值的占比值。 proportion = data.cumsum() / data.sum() # 用布爾索引列出大於等於0.8的數值列表,而列表里第一行就是大於80%的關鍵點,我們取得它的索引名稱。 key = proportion[proportion >= 0.8].index[0] # 根據之前得到的索引名稱,就可以從data數據中得到該名稱的索引位置。 key_number = data.index.tolist().index(key) proportion.plot(style='--ko', secondary_y=True, color='#FFA500') plt.axvline(key_number, linestyle='--', color='red') for x, y, s in zip(range(len(data)), proportion.values, proportion): if x == key_number: plt.text(key_num+0.2, y-0.035, '累計占比為 {:.2%}'.format(s), color='red', fontsize=12) else: plt.text(x+0.3, y-0.035, "{:.2%}".format(s), fontsize=12, horizontalalignment='center', color='black') plt.ylabel('銷售(比例)') plt.legend(['累積占比'], loc='upper center')
總結
畫帕累托圖最重要的幾點是要將數據從大到小排序,這主要是為了能體現帕累托法則的二八法則,少數掌握多數的原理。當數據以降序的方式排列后,計算每個列數據累計占比百分比數值。有了百分比數值,我們就可以將數據可視化,可視化后可以很清楚的從圖中來區分哪些對應的產品滿足了>=80%的貢獻。