用Python怎样画子弹图,构建图表方法是什�
Admin 2022-05-21 群英技术资�
一个子弹图约定俗成的定义:
子弹图使用长�/高度、位置和颜色对数据进行编码,以显示与目标和性能带相比的实际情况
我们先来看下子弹图大概长什么样子:
子弹图具有单一的主要度量(例如,当前年初至今的收入),将该度量与一个或多个其他度量进行比较以丰富其含义(例如,与目标相比),并将其显示在性能的定性范围的背景,例如差、满意和好。定性范围显示为单一色调的不同强度,使色盲者可以辨别它们,并将仪表板上的颜色使用限制在最低限�
好了,差不多这就是子弹图的应用场景和绘制标准了,下面我们就开始制作吧
思路大致是,可以使用堆叠条形图来表示各种范围,并使用另一个较小的条形图来表示值,最后,用一条垂直线标记目标
可以看出,我们需要多个组件图层,使用 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)
上面我就完成了子弹图的简单制作,但是我们所有的测试数值都是写死的,下面我们编写一个可以填写任意数值的代码
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 well h = limits[-1] / 10 # Use the green palette as a sensible default if palette is None: palette = sns.light_palette("green", len(limits), reverse=False) # Must be able to handle one or many data sets via multiple subplots if 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 subplot for idx, item in enumerate(data): # Get the axis from the array of axes returned when the plot is created if len(data) > 1: ax = axarr[idx] # Formatting to get rid of extra marking clutter 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): # Draw the bar ax.barh([1], lim - prev_limit, left=prev_limit, height=h, color=palette[idx2]) prev_limit = lim rects = ax.patches # The last item in the list is the value we're measuring # Draw the value we're measuring ax.barh([1], item[1], height=(h / 3), color=bar_color) # Need the ymin and max in order to make sure the target marker # fits ymin, ymax = ax.get_ylim() ax.vlines( item[2], ymin * .9, ymax * .9, linewidth=1.5, color=target_color) # Now make some labels 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)
代码虽然看起来有点长,但是其实都是上面步骤的叠加,都比较简单,就不再重复说明了
我们直接调用一下看看效果:
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)
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:[email protected]进行举报,并提供相关证据,查实之后,将立刻删除涉嫌侵权内容�
猜你喜欢
这篇文章主要介绍了教你怎么用Python实现多路径迷�,文中有非常详细的代码示例,对正在学习python的小伙伴们有非常好的帮助,需要的朋友可以参考下
在使用python中,你会遇到一个词,就是堆排序。那堆排序是什么呢?堆排序看字面意思是一种排序方法,那堆是什么呢?堆是一个近似完全二叉树的结构,并同时满足堆积的性质。其实堆排序是指利用堆这种数据结构所设计的一种排序算法。认识了堆排序,那你知道堆排序在python中如何实现吗�
这篇文章主要介绍了Python函数值传递引用传递及形式参数和实际参数的区别,具有一定的参考价值,需要的小伙伴可以参考一下,希望对你的学习有所帮助
这篇文章主要介绍了解决pytorch rnn 变长输入序列的问题,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐�
一些朋友应该有玩过吃豆人游戏,就是通过移动吃豆人吃豆豆来获得分数,同时要躲避怪物这样的玩法。小编认为是比较有趣的,因此给大家分享使用Python实现简单的吃豆人游戏代码,感兴趣的朋友可以参考学习�
成为群英会员,开启智能安全云计算之旅
立即注册Copyright © QY Network Company Ltd. All Rights Reserved. 2003-2020 群英 版权所�
增值电信经营许可证 : B1.B2-20140078