日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > python >内容正文

python

用 Python 制作子弹图也这么简单,爱了~

發布時間:2024/9/16 python 47 豆豆
生活随笔 收集整理的這篇文章主要介紹了 用 Python 制作子弹图也这么简单,爱了~ 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

眾所周知,Python 的應用是非常廣泛的,今天我們就通過 matplotlib 庫學習下如何制作精美的子彈圖

1什么是子彈圖

一個子彈圖約定俗成的定義

子彈圖使用長度/高度、位置和顏色對數據進行編碼,以顯示與目標和性能帶相比的實際情況

我們先來看下子彈圖大概長什么樣子

子彈圖具有單一的主要度量(例如,當前年初至今的收入),將該度量與一個或多個其他度量進行比較以豐富其含義(例如,與目標相比),并將其顯示在性能的定性范圍的背景,例如差、滿意和好。定性范圍顯示為單一色調的不同強度,使色盲者可以辨別它們,并將儀表板上的顏色使用限制在最低限度

好了,差不多這就是子彈圖的應用場景和繪制標準了,下面我們就開始制作吧

2構建圖表

思路大致是,可以使用堆疊條形圖來表示各種范圍,并使用另一個較小的條形圖來表示值,最后,用一條垂直線標記目標

可以看出,我們需要多個組件圖層,使用 matplotlib 來實現會比較方便

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

這里我們還導入了 Seaborn,是因為 Seaborn 有一些非常有用的工具來管理調色板,利用這種功能比嘗試以其他方式復制它更容易

我們需要生成調色板的主要原因是我們很可能希望為各種定性范圍生成視覺上吸引人的配色方案,直接使用 seaborn 來完成會方便很多

在下面的例子中,我們可以使用 palplot 便利函數來顯示 5 種綠色色調的調色板

sns.palplot(sns.light_palette("green",?5))

sns.palplot(sns.light_palette("purple",8,?reverse=True))

以相反的順序制作 8 種不同深淺的紫色

我們現在知道了如何設置調色板,接下來讓我們使用 Matplotlib 根據上面列出的原則創建一個簡單的子彈圖

首先,定義我們想要繪制的值

limits?=?[80,?100,?150] data_to_plot?=?("Example?1",?105,?120)

這個將創建 3 個范圍:0-80、81-100、101-150 和一個值為 105 和目標線為 120 的“示例”線 接下來,構建一個藍色調色板:

palette?=?sns.color_palette("Blues_r",?len(limits))

接下來是構建范圍的堆積條形圖:

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

然后我們可以添加一個較小的條形圖來表示 105 的值:

ax.barh([1],?data_to_plot[1],?color='black',?height=5)

已經初見雛形了

最后一步是使用 axvline 添加目標標記:

ax.axvline(data_to_plot[2],?color="gray",?ymin=0.10,?ymax=0.9)

上面我就完成了子彈圖的簡單制作,但是我們所有的測試數值都是寫死的,下面我們編寫一個可以填寫任意數值的代碼

3最終代碼

def?bulletgraph(data=None,?limits=None,?labels=None,?axis_label=None,?title=None,size=(5,?3),?palette=None,?formatter=None,?target_color="gray",bar_color="black",?label_color="gray"):#?Determine?the?max?value?for?adjusting?the?bar?height#?Dividing?by?10?seems?to?work?pretty?wellh?=?limits[-1]?/?10#?Use?the?green?palette?as?a?sensible?defaultif?palette?is?None:palette?=?sns.light_palette("green",?len(limits),?reverse=False)#?Must?be?able?to?handle?one?or?many?data?sets?via?multiple?subplotsif?len(data)?==?1:fig,?ax?=?plt.subplots(figsize=size,?sharex=True)else:fig,?axarr?=?plt.subplots(len(data),?figsize=size,?sharex=True)#?Add?each?bullet?graph?bar?to?a?subplotfor?idx,?item?in?enumerate(data):#?Get?the?axis?from?the?array?of?axes?returned?when?the?plot?is?createdif?len(data)?>?1:ax?=?axarr[idx]#?Formatting?to?get?rid?of?extra?marking?clutterax.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?=?0for?idx2,?lim?in?enumerate(limits):#?Draw?the?barax.barh([1],?lim?-?prev_limit,?left=prev_limit,?height=h,color=palette[idx2])prev_limit?=?limrects?=?ax.patches#?The?last?item?in?the?list?is?the?value?we're?measuring#?Draw?the?value?we're?measuringax.barh([1],?item[1],?height=(h?/?3),?color=bar_color)#?Need?the?ymin?and?max?in?order?to?make?sure?the?target?marker#?fitsymin,?ymax?=?ax.get_ylim()ax.vlines(item[2],?ymin?*?.9,?ymax?*?.9,?linewidth=1.5,?color=target_color)#?Now?make?some?labelsif?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)

代碼雖然看起來有點長,但是其實都是上面步驟的疊加,都比較簡單,就不再重復說明了

我們直接調用一下看看效果

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="Performance?Measure",?label_color="black",bar_color="#252525",?target_color='#f7f7f7',title="銷售代表表現")

我們還可以進行一些優化,格式化 x 軸以便更一致地顯示信息

在下面這個例子中,我們可以衡量一家假設公司的營銷預算績效

def?money(x,?pos):'The?two?args?are?the?value?and?tick?position'return?"${:,.0f}".format(x)money_fmt?=?FuncFormatter(money) data_to_plot3?=?[("HR",?50000,?60000),("Marketing",?75000,?65000),("Sales",?125000,?80000),("R&D",?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="營銷渠道預算績效",formatter=money_fmt)

看起來效果都不錯哦,怎么樣,一起跟著做起來吧!

END

推薦閱讀牛逼!Python常用數據類型的基本操作(長文系列第①篇) 牛逼!Python的判斷、循環和各種表達式(長文系列第②篇)牛逼!Python函數和文件操作(長文系列第③篇)牛逼!Python錯誤、異常和模塊(長文系列第④篇)

總結

以上是生活随笔為你收集整理的用 Python 制作子弹图也这么简单,爱了~的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。