熱線電話:13121318867

登錄
首頁大數據時代對比學習,用Excel和Python繪制子彈圖
對比學習,用Excel和Python繪制子彈圖
2021-07-09
收藏

來源:數據STUDIO

作者:云朵君

今天給大家帶來一篇比較有意思的可視化圖——子彈圖詳細繪圖教程。對比Excel與Pyhton,手把手教你繪制高大上的子彈圖。

P.S. 本文使用Excel for Mac作為演示,Windows Excel操作稍有不同,差異大的地方文中有額外解釋,總體繪圖步驟和思想是一致的,不影響理解和閱讀。

1、子彈圖

子彈圖的樣子很像子彈射出后帶出的軌道,所以稱為子彈圖(英文名:Bullet Graph)。子彈圖的發明是為了取代儀表盤上常見的那種里程表,時速表等基于圓形的信息表達方式。

子彈圖的特點如下:

  • 每一個單元的子彈圖只能顯示單一的數據信息源
  • 通過添加合理的度量標尺可以顯示更精確的階段性數據信息
  • 通過優化設計還能夠用于表達多項同類數據的對比
  • 可以表達一項數據與不同目標的校對結果

子彈圖無修飾的線性表達方式使我們能夠在狹小的空間中表達豐富的數據信息,線性的信息表達方式與我們習以為常的文字閱讀相似,相對于圓形構圖的信息表達,在信息傳遞上有更大的效能優勢。

2、子彈圖的構成

下圖為子彈圖的結構,以及與柱形圖的對比

對比學習,用Excel和Python繪制子彈圖

主要數據值由圖表中間主條形的長度所表示,稱為功能度量(Feature Measure);而與圖表方向垂直的直線標記則稱為比較度量(Comparative Measure),用來與功能度量所得數值進行比較。如果主條形長度超越比較度量標記的位置,則代表數據達標。

功能度量背后的分段顏色條形用來顯示定性范圍得分。每種色調(如上面示例中三種不同深度的灰色)表示不同表現范圍等級,如欠佳、平均和良好。當使用子彈圖時,建議最多使用五個等級。

3、子彈圖和柱狀圖對比

柱狀圖主要用于多個分類間的數據(大小、數值)的對比。

子彈圖主要用于各個分類間各自的數值所處狀態與測量標記的對比,突出的是每個分類自身的情況,沒有分類間的比較,用于展示各個分類的子彈圖單元相對獨立。

一、Excel繪制子彈圖

子彈圖分為橫向子彈圖和縱向子彈圖。兩者繪制方法有所差異!

縱向子彈圖

用Excel繪制縱向子彈圖較為簡單。選擇需要繪制的數據,插入簇狀柱形圖,然后更改圖表類型。將"目標值"與"銷售額"更改為次坐標軸,圖表類型分別為"帶數據標記的折線圖"和"簇狀柱形圖","合格值"與"挑戰值"為"堆積柱形圖"。

最后更改實際銷售額"簇狀柱形圖"的柱子寬度(調整間隙寬度),和目標值的"帶數據標記的折線圖"標記類型(-)和大小(18)。

對比學習,用Excel和Python繪制子彈圖

橫向子彈圖

橫向子彈圖與縱向子彈圖不同,它的繪制方法較為復雜,下面我們一步步帶你操作。

對比學習,用Excel和Python繪制子彈圖

1、數據準備

已有字段
地區,目標銷售額,實際銷售額,挑戰銷售額,合格銷售額五個字段。

添加字段

  • 挑戰=挑戰值-合格值
  • y-次軸,以0.5為開始值,級差為0.5的等差數列,用于散點圖的y軸

2、Step01

選擇數據,繪制橫行堆積條形圖。

對比學習,用Excel和Python繪制子彈圖

3、Step02

插入一個銷售額列,并選擇對應x/y軸數據。

對比學習,用Excel和Python繪制子彈圖

選擇上步添加的銷售額堆積條形圖,修改圖表類型為散點圖,設置坐標軸類型為【次要坐標軸】

對比學習,用Excel和Python繪制子彈圖

4、Step03

選擇合格值數據條,設置【間隙寬度】為50%。并按照銷售額的方法添加目標值散點圖。

對比學習,用Excel和Python繪制子彈圖

5、Step04

實際銷售額與目標銷售額的繪制。這一步上win和mac兩者差異較大,因此在這里分別說明了步驟。

mac方法:

單擊【添加圖表元素】-【誤差線】-【標準誤差線】,點擊并刪除垂直誤差線,選擇“水平誤差線”并設置誤差線格式,方向為【負偏差】,末端樣式為【無線端】,誤差量為【自定義】,【指定值】數據來源為銷售額單元格。如下圖所示。

對比學習,用Excel和Python繪制子彈圖


win方法:

單擊【添加圖表元素】-【誤差線】-【其他誤差線選項】,在打開的窗格中選擇“水平誤差線”,方向為【負偏差】,末端樣式為【無線端】,誤差量為【自定義】,在打開的【自定義錯誤欄】中選【負錯誤值】,數據來源為銷售額單元格。

6、Step05

先選擇銷售額水平誤差線,增加線條的粗細至合適寬度,標記點設為無。

再按照上一步方法設置目標值,添加誤差線,方向為垂直方向,無線端,誤差量為【固定值】至合適寬度。

對比學習,用Excel和Python繪制子彈圖

二、Python繪制子彈圖

Python繪制子彈圖方法也不復雜,這里需要借助seaborn調色板繪制子彈圖的背景顏色。配合使用matplotlib繪制條形圖和豎線條繪制實際值和目標值即可。

1、導入相應模塊

import matplotlib.pyplot as plt import seaborn as sns from matplotlib.ticker import FuncFormatter
%matplotlib inline

2、Seaborn調色板

sns.palplot(sns.light_palette("green", 5))
對比學習,用Excel和Python繪制子彈圖

增加調色板長度及顏色

sns.palplot(sns.light_palette("purple",8, reverse=True))
對比學習,用Excel和Python繪制子彈圖

3、設置要繪制的數據

limits = [80100150] data_to_plot = ("Example 1"105120) palette = sns.color_palette("Blues_r", len(limits))

4、嘗試構建第一個堆疊條形圖

fig, ax = plt.subplots()
ax.set_aspect('equal')
ax.set_yticks([1])
ax.set_yticklabels([data_to_plot[0]])

prev_limit = 0 for idx, lim in enumerate(limits):
    ax.barh([1], lim-prev_limit, left=prev_limit, height=15, color=palette[idx])
    prev_limit = lim
對比學習,用Excel和Python繪制子彈圖

增加測量值

# 畫出我們要測量的值 ax.barh([1], data_to_plot[1], color='black', height=5)
對比學習,用Excel和Python繪制子彈圖

添加目標垂直線

ax.axvline(data_to_plot[2], color="blue", 
           ymin=0.10, ymax=0.9)
對比學習,用Excel和Python繪制子彈圖

5、定義完整的函數

函數參數

data: 標簽、測量和目標的列表
limits: 范圍值列表
labels: 限制范圍的描述列表
axis_label: 描述x軸的字符串
title: 圖標題
size: 繪圖尺寸元組
palette: seaborn調色板
formatter: matplotlib formatter 對象的x軸
target_color: 目標行顏色字符串
bar_color: 小條的顏色字符串
label_color: 限制標簽文本的顏色字符串

bulletgraph(data=None, limits=None, labels=None, axis_label=None,
            title=None, size=(53), palette=None, formatter=None,
            target_color="gray", bar_color="black", label_color="gray")

6、子彈圖01

# 數據準備 data_to_plot2 = [("張三", 105, 120),
                 ("李斯", 99, 110),
                 ("王武", 109, 125),
                 ("侯奇", 135, 123),
                 ("巴蜀", 45, 105)] # 繪制圖 bulletgraph(data_to_plot2, limits=[20, 60, 100, 160], 
            labels=["Poor""OK""Good""Excellent"], 
            size=(8,5), axis_label="績效考核", 
            label_color="black", bar_color="#252525", 
            target_color='#f7f7f7',             title="銷售代表績效")
對比學習,用Excel和Python繪制子彈圖

7、子彈圖02

money_fmt = FuncFormatter(money) # 數據準備 data_to_plot3 = [("Print", 50000, 60000),
                 ("Billboards", 75000, 65000),
                 ("Radio", 125000, 80000),
                 ("Online", 195000, 115000)] # 設置調色板 palette = sns.light_palette("grey", 3, reverse=False)
bulletgraph(data_to_plot3, 
            limits=[50000, 125000, 200000], 
            labels=["Below""On Target""Above"], 
            size=(10,5), axis_label="Annual Budget", 
            label_color="black", bar_color="#252525", 
            target_color='#f7f7f7', palette=palette,             title="Marketing Channel Budget Performance", 
            formatter=money_fmt)
對比學習,用Excel和Python繪制子彈圖

8、子彈圖特點

總結一下,子彈圖有以下特點:

  1. 有設置定性的數據范圍,采用同一色系中不同深淺的顏色來表示。比如上圖中有Bad、Good、Excellent三個定性的數值范圍(也可以采用更多個,但是不建議過多,一般3~5個即可)。
  2. 主體數據條柱,一般用較深的顏色表示,可以吸引人的眼球,比如我們用來表達實際完成情況。這個柱子與定性范圍的柱子是重疊在一起的,但是比它們要窄。
  3. 有一個橫線(豎線)作為主要標記標識,可以用來表示目標,方便直觀地對比是否達成目標。
  4. 刻度量表,可以清晰地表達具體的數值,這里我們就用坐標軸表示。
  5. 文本標簽,可以用來表示圖表的信息內容。

9、附錄子彈圖完整函數

def bulletgraph(data=None, limits=None, labels=None, axis_label=None, title=None,
                size=(53), palette=None, formatter=None, target_color="gray",
                bar_color="black", label_color="gray"):     """ Build out a bullet graph image
        Args:
            data = 標簽、測量和目標的列表
            limits = 范圍值列表
            labels = 限制范圍的描述列表
            axis_label = 描述x軸的字符串
            title = 圖標題
            size = 繪圖尺寸元組
            palette = seaborn調色板
            formatter = matplotlib formatter 對象的x軸
            target_color = 目標行顏色字符串
            bar_color = 小條的顏色字符串
            label_color = 限制標簽文本的顏色字符串
        Returns:
            a matplotlib figure
    """     # 確定調整工具條高度的最大值     # 除以10似乎很有效     h = limits[-1] / 10     # 使用綠色調色板作為合理的默認設置     if palette is None:
        palette = sns.light_palette("green", len(limits), reverse=False)

    # 必須能夠通過多個子圖處理一個或多個數據集     if len(data) == 1:
        fig, ax = plt.subplots(figsize=size, sharex=True)
    else:
        fig, axarr = plt.subplots(len(data), figsize=size, sharex=True)

    # 將每個項目符號圖形條添加到副圖中     for idx, item in enumerate(data):

        # 從創建繪圖時返回的軸數組中獲取軸         if len(data) > 1:
            ax = axarr[idx]

        # 格式化以消除額外的標記混亂         ax.set_aspect('equal')
        ax.set_yticklabels([item[0]])
        ax.set_yticks([1])
        ax.spines['bottom'].set_visible(False)
        ax.spines['top'].set_visible(False)
        ax.spines['right'].set_visible(False)
        ax.spines['left'].set_visible(False)

        prev_limit = 0         for idx2, lim in enumerate(limits):
            # 繪制條形圖             ax.barh([1], lim - prev_limit, left=prev_limit, height=h,
                    color=palette[idx2])
            prev_limit = lim
        rects = ax.patches
        # 列表中的最后一項是我們要測量的值          # 繪制我們正在測量的值         ax.barh([1], item[1], height=(h / 3), color=bar_color)

        # 需要ymin和max,以確保目標標記適合         ymin, ymax = ax.get_ylim()
        ax.vlines(
            item[2], ymin * .9, ymax * .9, linewidth=1.5, color=target_color)

    # 現在做一些標簽     if labels is not None:
        for rect, label in zip(rects, labels):
            height = rect.get_height()
            ax.text(
                rect.get_x() + rect.get_width() / 2,
                -height * .4,
                label,
                ha='center',
                va='bottom',
                color=label_color)
    if formatter:
        ax.xaxis.set_major_formatter(formatter)
    if axis_label:
        ax.set_xlabel(axis_label)
    if title:
        fig.suptitle(title, fontsize=14)
    fig.subplots_adjust(hspace=0)

數據分析咨詢請掃描二維碼

若不方便掃碼,搜微信號:CDAshujufenxi

數據分析師資訊
更多

OK
客服在線
立即咨詢
日韩人妻系列无码专区视频,先锋高清无码,无码免费视欧非,国精产品一区一区三区无码
客服在線
立即咨詢