使用 seaborn 绘制累积条形图

最近想看下某地区近几年降雨量如何变化,获得的数据是分年分月的,打算绘制按年份累积每月降雨量的条形图。搜索教程,主要有以下几种方法。

  • 方法1:使用 seaborn 的 barplot() 函数,在 x 相同位置,分别绘制112月累积量、111月累积量、1~10月累积量,以此类推直至1月降雨量。每次绘制使用颜色不同,后绘制的相当于把前绘制的条状遮住一部分。需要调用12次 barplot() 函数。参考文章点这里
  • 方法2:使用 matplotlib 的 bar() 函数,按年分别绘制每月的降雨量条形图,通过参数bottom指定所绘制的月份条形图下方是哪个月的条形图,相当于一层一层的柱子码起来。需要调用12次 bar() 函数。参考文章点这里
  • 方法3:使用 seaborn 的 histplot() 函数,设置 multiple 参数为 stackweights 参数为需要累积的量,既可绘制累积条形图。只需条用1次 histplot() 函数。参考文章点这里。这篇文章另外还介绍了如何使用 matplotlib、pandas、plotnine、altair 绘制累积条形图。

前两种方法太繁琐,采用第3种方法。搜相关教程有个感悟,要想快速准确找到资料,搜英文文章,或者直接在 seaborn 官方教程找。

下面开始代码操练。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
import pandas as pd
import seaborn as sns
from matplotlib import pyplot as plt
import matplotlib.font_manager as font_manager
%matplotlib inline

rc = {'axes.unicode_minus': False}
sns.set(context='notebook', style='ticks', font='Noto Sans SC', rc=rc)

temps = pd.read_csv('泾河站-2006-2021-月度气象数据-来自WheatA-整理后.csv', encoding="gbk")
ax = sns.histplot(
    data=temps,
    x='年份',
    # Use the value variable here to turn histogram counts into weighted
    # values.
    weights='降水量(mm)',
    hue='月份',
    multiple='stack'
)

绘制出来的图确实是个月降雨量累积,但有以下几个问题:

  1. 数据从 2006 年至 2021 年,应该有 16 条柱子,图中只有10条,需要通过 bins 参数指定柱子数量。
  2. 图列挡住图像了,需要将图幅扩大。
  3. 相邻的柱子紧挨在一起,看着不舒服。
  4. x 轴的刻度线没在柱子下方正中间,需要指定刻度线位置。
  5. x 轴刻度标签没有将所有年份都显示,需要指定刻度线标签。
  6. y 轴标签应该是降雨量,需指定。
  7. 没有图名,需添加。
  8. x、y 轴标签文字字体有些小,需加大。
  9. 更改柱子颜色为绿色。

解决以上问题,优化后代码如下。具体参数说明见代码注释。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
# rc 参数中设置显示负号、图幅尺寸
rc = {'axes.unicode_minus': False, 'figure.figsize':(11.0, 6.0)}
# 设置绘图样式、中文字体
sns.set(context='notebook', style='ticks', font='Noto Sans SC', rc=rc)
# 绘制累积条形图
ax = sns.histplot(
    data=temps,
    x='年份',
    # 将累积量作为加权
    weights='降水量(mm)',
    # 不同月份按不同颜色显示
    hue='月份',
    # 指定为累积
    multiple='stack',
    # 在柱子间添加白线
    edgecolor='white',
    # 按指定比例缩小柱子宽度,以避免柱子互相紧挨
    shrink=0.8,
    # 指定柱子数量
    bins=16,
    # 将x轴刻度线置于柱子下方正中间
    discrete=True,
    # 指定色盘,采用绿色为基础色,生成12个颜色,适用于离散性数据
    palette=sns.light_palette('seagreen', n_colors=12),
)
# 指定x轴刻度线位置
x = range(2006, 2022)
ax.set_xticks(x)
# 指定x轴刻度线标签
xlabs = range(2006, 2022)
ax.set_xticklabels(xlabs)
# 设置x、y轴标签及字体大小
ax.set_ylabel("降雨量/mm", fontsize=14)
ax.set_xlabel("年份", fontsize=14)
# 设置图名及字体大小
ax.set_title('年降雨量', fontsize=14)