查看原文
其他

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

凹凸数据 2021-08-09

The following article is from 林骥 Author 林骥

每晚九点,我们准时相约  


大家好,我是朱小五



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


比如说,假设某公司一月份销售额 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 来完成,以提升自己的工作效率和工作质量,让自己有时间去做更多更有价值的事情。


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


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








近期文章,点击图片即刻查看






后台回复关键词「进群」,即刻加入读者交流群~


不知道大家还对什么图形感兴趣呢?

朱小五

    您可能也对以下帖子感兴趣

    文章有问题?点此查看未经处理的缓存