结果:
import matplotlib.pyplot as plt
import matplotlib.ticker as ticker
import numpy as np
def lolly_plot(x, y, color_lis, breaks, back_color,
title, sub_title):
# 获取每个点的颜色
colors = [assign_color(temperature, breaks, color_lis) for temperature in temperature_changes]
# 创建图形
fig, ax = plt.subplots(figsize=(10, 12))
# 绘制棒棒糖
ax.vlines(x=x, ymin=0, ymax=y, color=colors, alpha=0.8, linewidth=2) # 竖线
ax.scatter(x, y, color=colors, s=50, zorder=3) # 点
# 添加水平线(0℃、-0.4℃、0.8℃)
ax.axhline(0.8, color=color_lis[-1], linewidth=1, alpha=0.5)
ax.axhline(0.4, color=color_lis[4], linewidth=1, alpha=0.5)
ax.axhline(0, color='black', linewidth=1)
ax.axhline(-0.4, color=color_lis[0], linewidth=1, alpha=0.5)
# 设置坐标轴
ax.set_xlim(1880, 2020)
ax.set_ylim(-0.5, 1.0)
ax.set_xticks(np.arange(1880, 2021, 20))
ax.set_yticks([-0.4, 0, 0.4, 0.8])
# 去掉顶部和右侧的边框线
ax.spines['top'].set_visible(False)
ax.spines['right'].set_visible(False)
# 设置标签
ax.set_title(title, fontsize=20, weight='bold', ha='left', x=0.02)
ax.text(0.02, 0.99, sub_title, transform=ax.transAxes, fontsize=12, va='top', color='gray')
# 设置背景颜色
fig.patch.set_color(back_color)
ax.patch.set_color(back_color)
# 显示图像
plt.tight_layout() # 让图表更贴近边框
plt.show()
# 分段赋色规则(对应原图的分块颜色)
def assign_color(value, breaks, colors):
"""
分段赋色。小于等于第一个断点为第一个区间,大于第一个断点、小于等于第二个断点为第二个区间...,大于最后一个断点为最后一个区间。
breaks:断点。 breaks至少比colors少一个。
colors:颜色。从数值最低的颜色到数值最高的颜色,依次排列。
"""
# 从小到大,依次排列断点。
breaks = list(breaks)
breaks.sort(reverse=False) # 升序排列
# bisect_left: 二分法查找某个值所在的区间。(若为边界值,则落入左侧区间。)
index = bisect_left(breaks, value)
return colors[index]
if __name__ == '__main__':
# 年份数据
years = np.arange(1880, 2021)
# 模拟温度变化数据,接近实际趋势
temperature_changes = np.zeros(len(years))
# 分段设定温度变化趋势,并加入波动
np.random.seed(0)
temperature_changes[0:60] = np.linspace(-.5, -.2, 60) + np.random.normal(0, .05, 60) # 1880-1940 年
temperature_changes[60:100] = np.linspace(-.2, .1, 40) + np.random.normal(0, .03, 40) # 1940-1980 年
temperature_changes[100:] = np.linspace(.1, .9, len(years) - 100) + np.random.normal(0, .02, len(years) - 100)
# 为每个温度区间分配颜色
color_lis = ['#212B4E', '#0571B6', '#17B3BA', '#FDBE85', '#D94701', '#871A03']
breaks = [-0.25, -0.1, 0, 0.3, 0.52]
back_color = '#FEFAEF'
# 设置标题
title = "Global Land-Ocean Temperature Index"
text = "Change in global surface temperature compared to the long-term average\nfrom 1951 to 1980"
lolly_plot(years, temperature_changes, color_lis, breaks, back_color, title, text)