瀑布图有什么用?用python怎么画?

  • 2020 年 3 月 18 日
  • 笔记

瀑布图,因为形似瀑布而得名,它能够比较好地体现数据分析的对比思维和细分思维。

比如说,假设某公司一月份销售额 1000 万,二月份销售额 500 万,为了体现各地区的销售额变化,我们可以画一张瀑布图如下。

通过对比,发现销售额下降了 50%;通过细分,发现不同地区的销售变化差异较大,其中上海地区的销售额增加了 30 万,湖北地区的销售额下降了 150 万,其他地区的销售额也都有不同程度的下降。

你可能会问,销售额增加的原因是什么?销售额下降的原因又是什么?这些都需要根据业务的实际情况,具体问题具体分析,找到问题的本质原因,从而有针对性地提出解决问题的办法,本文给出的数据完全是虚拟的,所以这里不做进一步的分析。

本文的重点,是介绍怎么使用 Python 画出瀑布图,让你能够举一反三,应用于自己的实际工作当中。你只需要把数据文件准备好,然后运行一遍代码,就能自动生成所需的瀑布图。

1. 读取数据

首先,我们导入所需的库,并从 Excel 文件中读取不同地区的销售额数据。

# 导入所需的库  import pandas as pd  import numpy as np  import matplotlib.pyplot as plt    # 设置正常显示中文标签  plt.rcParams['font.sans-serif'] = ['SimHei']    ########## 准备绘图数据 ###############    # 从 Excel 文件中读取数据,第一列设置为索引  sale = pd.read_excel('data/不同地区的销售额变化.xlsx', index_col=0)    sale

2. 处理数据

其次,我们对原始数据进行处理,把数据转换成绘图所需的格式。

######### 处理数据 ###############    # 计算销售额的变化  sale['销售变化'] = sale.iloc[:, 1] - sale.iloc[:, 0]    # 把销售汇总作为第一行  change = pd.concat([pd.DataFrame(sale.sum()).T, sale])    # 修改第一行的索引名称:上个月  change.rename(index={0: sale.columns[0]}, inplace=True)    # 设置瀑布图的第一个数值  change.iloc[0, 2] = change.iloc[0, 0]    # 排除没有变化的项目  change = change[abs(change.销售变化) > 0]    # 降序排列  change = change.sort_values('销售变化', ascending=False)    # 不要包含汇总,后面会自动计算  index = change.index  data = change.销售变化  trans = pd.DataFrame(data=data, index=index)    # 为瀑布图创建空白序列,用于把柱子撑起来  blank = trans.销售变化.cumsum().shift(1).fillna(0)    # 计算瀑布图的最后一个数值:当月收入  thismonth = sale.columns[1]  total = trans.sum().销售变化    # 设置瀑布图中每个项目的变化  step = blank.reset_index(drop=True).repeat(3).shift(-1)  step[1::3] = np.nan    # 最后一根柱子是从 0 开始  blank.loc[thismonth] = 0  trans.loc[thismonth] = total    trans

3. 开始画图

接下来,我们开始画图,在画图函数所使用的数据中,trans 存储的是瀑布图中柱子对应的数据,blank 存储的是柱子底端的高度数据。

import numpy as np  import pandas as pd  import matplotlib.pyplot as plt  from datetime import timedelta    # 正常显示中文标签  plt.rcParams['font.sans-serif'] = ['SimHei']    # 正常显示负号  plt.rcParams['axes.unicode_minus'] = False    # 读取每日销售数据  df = pd.read_excel('./data/2019年9月每日销售.xlsx')    # 定义画图的数据  x = df.日期  y = df.实际销量    # 定义颜色  color1 = '#0085c3'  color2 = '#7ab800'  color3 = '#dc5034'    # 设置图像大小  ########## 开始画图 ###############    # 设置标题  title = 'n各地区销售额变化瀑布图n'    # 使用 Pandas 中的画图函数  waterfall = trans.plot(kind='bar', stacked=True, bottom=blank, legend=None, figsize=(16, 8), fontsize=20, width=0.8)    # 设置 x 轴标签  waterfall.set_xlabel("")    # 计算标签位置的偏移量  max = trans.max()  neg_offset = max / 25  pos_offset = max / 50  plot_offset = int(max / 10)    # 获取标签的高度位置  y_height = trans.销售变化.cumsum().shift(1).fillna(0)    # 循环设置标签  loop = 0  for index, row in trans.iterrows():      x = row['销售变化']      # 最后一个标签的位置不要双倍      if x == total:          y = y_height[loop]      else:          y = y_height[loop] + x        # 决定向上还是向下偏移      if x > 0:          y += pos_offset      else:          y -= neg_offset        # 添加数字标签,负数用红色      waterfall.annotate("{:.1f}".format(x), (loop, y), ha="center", fontsize=20, color=('k' if x>0 else 'r'))      loop+=1    # 设置 y 轴的偏移量  waterfall.set_ylim(0, blank.max()+int(plot_offset))    # 设置 x 轴标签的角度  waterfall.set_xticklabels(trans.index, rotation=0)    # 设置标题并显示图片  plt.title(title, fontsize=36, loc='center', color='k')    plt.show()

运行之后得到的图片,就是本文开头显示的那张瀑布图。

4. 小结

本文介绍了瀑布图的一个应用案例,并给出了详细的 Python 实现代码,在公众号后台发送“瀑布”两个字,可以获得本文的数据文件和完整代码。

虽然 Excel 也能画瀑布图,但是我个人觉得用 Python 能够更加灵活高效。

Python 能让数据分析等工作变得更加自动化、标准化、流程化。

所以,我渐渐地把很多工作,都转换为使用 Python 来完成,以提升自己的工作效率和工作质量,让自己有时间去做更多更有价值的事情。

多花一些时间,去提升自己的能力,让自己获得成长和进步,我觉得是非常值得的,所谓“磨刀不误砍柴工”,这也是我们要学习时间管理的重要原因之一。

最后再次重复一遍哈,在公众号后台发送“瀑布”两个字,可以获得本文的数据文件和完整代码。