瀑布图有什么用?用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 来完成,以提升自己的工作效率和工作质量,让自己有时间去做更多更有价值的事情。
多花一些时间,去提升自己的能力,让自己获得成长和进步,我觉得是非常值得的,所谓「磨刀不误砍柴工」,这也是我们要学习时间管理的重要原因之一。
最后再次重复一遍哈,在公众号后台发送「瀑布」两个字,可以获得本文的数据文件和完整代码。