如何使用Python创建一个瀑布图
今天小编给大家分享一下如何使用Python创建一个瀑布图的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来了解一下吧。
成都创新互联公司成都网站建设按需规划网站,是成都网站营销推广公司,为成都搬家公司提供网站建设服务,有成熟的网站定制合作流程,提供网站定制设计服务:原型图制作、网站创意设计、前端HTML5制作、后台程序开发等。成都网站推广热线:13518219792
创建图表
首先,执行标准的输入,并确保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)
首先,我们得到累积和。
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')
以上就是“如何使用Python创建一个瀑布图”这篇文章的所有内容,感谢各位的阅读!相信大家阅读完这篇文章都有很大的收获,小编每天都会为大家更新不同的知识,如果还想学习更多的知识,请关注创新互联行业资讯频道。
文章标题:如何使用Python创建一个瀑布图
本文链接:http://azwzsj.com/article/ihodhd.html