介绍
对于绘制某些类型的数据来说,瀑布图是一种十分有用的工具。不足为奇的是,我们可以使用Pandas和matplotlib创建一个可重复的瀑布图。
在往下进行之前,我想先告诉大家我指代的是哪种类型的图表。我将建立一个维基百科文章中描述的2D瀑布图。
这种图表的一个典型的用处是显示开始值和结束值之间起“桥梁”作用的+和-的值。因为这个原因,财务人员有时会将其称为一个桥梁。跟我之前所采用的其他例子相似,这种类型的绘图在Excel中不容易生成,当然肯定有生成它的方法,但是不容易记住。
关于瀑布图需要记住的关键点是:它本质上是一个堆叠在一起的条形图,不过特殊的一点是,它有一个空白底栏,所以顶部栏会“悬浮”在空中。那么,让我们开始吧。
创建图表
首先,执行标准的输入,并确保IPython能显示matplot图。
import numpy as np import pandas as pd import matplotlib.pyplot as plt %matplotlib inline
设置我们想画出瀑布图的数据,并将其加载到数据帧(DataFrame)中。
数据需要以你的起始值开始,但是你需要给出最终的总数。我们将在下面计算它。
index = ['sales','returns','credit fees','rebates','late charges','shipping'] data = {'amount': [350000,-30000,-7500,-25000,95000,-7000]} trans = pd.DataFrame(data=data,index=index)
我使用了IPython中便捷的display函数来更简单地控制我要显示的内容。
from IPython.display import display display(trans)
瀑布图的最大技巧是计算出底部堆叠条形图的内容。有关这一点,我从stackoverflow上的讨论中学到很多。
首先,我们得到累积和。
display(trans.amount.cumsum()) sales 350000 returns 320000 credit fees 312500 rebates 287500 late charges 382500 shipping 375500 Name: amount, dtype: int64
这看起来不错,但我们需要将一个地方的数据转移到右边。
blank=trans.amount.cumsum().shift(1).fillna(0) display(blank) sales 0 returns 350000 credit fees 320000 rebates 312500 late charges 287500 shipping 382500 Name: amount, dtype: float64
我们需要向trans和blank数据帧中添加一个净总量。
total = trans.sum().amount trans.loc["net"] = total blank.loc["net"] = total display(trans) display(blank)
sales 0 returns 350000 credit fees 320000 rebates 312500 late charges 287500 shipping 382500 net 375500 Name: amount, dtype: float64
创建我们用来显示变化的步骤。
step = blank.reset_index(drop=True).repeat(3).shift(-1) step[1::3] = np.nan display(step) 0 0 0 NaN 0 350000 1 350000 1 NaN 1 320000 2 320000 2 NaN 2 312500 3 312500 3 NaN 3 287500 4 287500 4 NaN 4 382500 5 382500 5 NaN 5 375500 6 375500 6 NaN 6 NaN Name: amount, dtype: float64
对于“net”行,为了不使堆叠加倍,我们需要确保blank值为0。
blank.loc["net"] = 0
然后,将其画图,看一下什么样子。
my_plot = trans.plot(kind='bar', stacked=True, bottom=blank,legend=None, title="2014 Sales Waterfall") my_plot.plot(step.index, step.values,'k')
看起来相当不错,但是让我们试着格式化Y轴,以使其更具有可读性。为此,我们使用FuncFormatter和一些Python2.7+的语法来截断小数并向格式中添加一个逗号。
def money(x, pos): 'The two args are the value and tick position' return "${:,.0f}".format(x) from matplotlib.ticker import FuncFormatter formatter = FuncFormatter(money)
然后,将其组合在一起。
my_plot = trans.plot(kind='bar', stacked=True, bottom=blank,legend=None, title="2014 Sales Waterfall") my_plot.plot(step.index, step.values,'k') my_plot.set_xlabel("Transaction Types") my_plot.yaxis.set_major_formatter(formatter)
完整脚本
基本图形能够正常工作,但是我想添加一些标签,并做一些小的格式修改。下面是我最终的脚本:
import numpy as np import pandas as pd import matplotlib.pyplot as plt from matplotlib.ticker import FuncFormatter #Use python 2.7+ syntax to format currency def money(x, pos): 'The two args are the value and tick position' return "${:,.0f}".format(x) formatter = FuncFormatter(money) #Data to plot. Do not include a total, it will be calculated index = ['sales','returns','credit fees','rebates','late charges','shipping'] data = {'amount': [350000,-30000,-7500,-25000,95000,-7000]} #Store data and create a blank series to use for the waterfall trans = pd.DataFrame(data=data,index=index) blank = trans.amount.cumsum().shift(1).fillna(0) #Get the net total number for the final element in the waterfall total = trans.sum().amount trans.loc["net"]= total blank.loc["net"] = total #The steps graphically show the levels as well as used for label placement step = blank.reset_index(drop=True).repeat(3).shift(-1) step[1::3] = np.nan #When plotting the last element, we want to show the full bar, #Set the blank to 0 blank.loc["net"] = 0 #Plot and label my_plot = trans.plot(kind='bar', stacked=True, bottom=blank,legend=None, figsize=(10, 5), title="2014 Sales Waterfall") my_plot.plot(step.index, step.values,'k') my_plot.set_xlabel("Transaction Types") #Format the axis for dollars my_plot.yaxis.set_major_formatter(formatter) #Get the y-axis position for the labels y_height = trans.amount.cumsum().shift(1).fillna(0) #Get an offset so labels don't sit right on top of the bar max = trans.max() neg_offset = max / 25 pos_offset = max / 50 plot_offset = int(max / 15) #Start label loop loop = 0 for index, row in trans.iterrows(): # For the last item in the list, we don't want to double count if row['amount'] == total: y = y_height[loop] else: y = y_height[loop] + row['amount'] # Determine if we want a neg or pos offset if row['amount'] > 0: y += pos_offset else: y -= neg_offset my_plot.annotate("{:,.0f}".format(row['amount']),(loop,y),ha="center") loop+=1 #Scale up the y axis so there is room for the labels my_plot.set_ylim(0,blank.max()+int(plot_offset)) #Rotate the labels my_plot.set_xticklabels(trans.index,rotation=0) my_plot.get_figure().savefig("waterfall.png",dpi=200,bbox_inches='tight')
运行该脚本将生成下面这个漂亮的图表:
最后的想法
如果你之前不熟悉瀑布图,希望这个示例能够向你展示它到底是多么有用。我想,可能一些人会觉得对于一个图表来说需要这么多的脚本代码有点糟糕。在某些方面,我同意这种想法。如果你仅仅只是做一个瀑布图,而以后不会再碰它,那么你还是继续用Excel中的方法吧。
然而,如果瀑布图真的很有用,并且你需要将它复制给100个客户,将会怎么样呢?接下来你将要怎么做呢?此时使用Excel将会是一个挑战,而使用本文中的脚本来创建100个不同的表格将相当容易。再次说明,这一程序的真正价值在于,当你需要扩展这个解决方案时,它能够便于你创建一个易于复制的程序。
我真的很喜欢学习更多Pandas、matplotlib和IPothon的知识。我很高兴这种方法能够帮到你,并希望其他人也可以从中学习到一些知识,并将这一课所学应用到他们的日常工作中。

Python适合数据科学、Web开发和自动化任务,而C 适用于系统编程、游戏开发和嵌入式系统。 Python以简洁和强大的生态系统着称,C 则以高性能和底层控制能力闻名。

2小时内可以学会Python的基本编程概念和技能。1.学习变量和数据类型,2.掌握控制流(条件语句和循环),3.理解函数的定义和使用,4.通过简单示例和代码片段快速上手Python编程。

Python在web开发、数据科学、机器学习、自动化和脚本编写等领域有广泛应用。1)在web开发中,Django和Flask框架简化了开发过程。2)数据科学和机器学习领域,NumPy、Pandas、Scikit-learn和TensorFlow库提供了强大支持。3)自动化和脚本编写方面,Python适用于自动化测试和系统管理等任务。

两小时内可以学到Python的基础知识。1.学习变量和数据类型,2.掌握控制结构如if语句和循环,3.了解函数的定义和使用。这些将帮助你开始编写简单的Python程序。

如何在10小时内教计算机小白编程基础?如果你只有10个小时来教计算机小白一些编程知识,你会选择教些什么�...

使用FiddlerEverywhere进行中间人读取时如何避免被检测到当你使用FiddlerEverywhere...

Python3.6环境下加载Pickle文件报错:ModuleNotFoundError:Nomodulenamed...

如何解决jieba分词在景区评论分析中的问题?当我们在进行景区评论分析时,往往会使用jieba分词工具来处理文�...


热AI工具

Undresser.AI Undress
人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover
用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool
免费脱衣服图片

Clothoff.io
AI脱衣机

AI Hentai Generator
免费生成ai无尽的。

热门文章

热工具

WebStorm Mac版
好用的JavaScript开发工具

Dreamweaver Mac版
视觉化网页开发工具

PhpStorm Mac 版本
最新(2018.2.1 )专业的PHP集成开发工具

螳螂BT
Mantis是一个易于部署的基于Web的缺陷跟踪工具,用于帮助产品缺陷跟踪。它需要PHP、MySQL和一个Web服务器。请查看我们的演示和托管服务。

禅工作室 13.0.1
功能强大的PHP集成开发环境