• 跟着顶级科研报告IPCC学绘图:温度折线/柱图/条带/双y轴


    复现IPCC气候变化过程图

    引言

    升温条带Warming stripes(有时称为气候条带,目前尚无合适且统一的中文释义)是数据可视化图形,使用一系列按时间顺序排列的彩色条纹来视觉化描绘长期温度趋势。

    图片

     

    在IPCC报告中经常使用这一方案

    图片

    IPCC是科研报告,同时也是向大众传播信息的媒介,变暖条纹体现了一种“极简主义” ,设想仅使用颜色来避免技术干扰,向非科学家直观地传达全球变暖趋势,非常值得我们学习。

    升温条带为何显著?

    近年来,极端天气事件越发频繁,而是成为一种常态。2022 年,暴雨季风引发了各地区的洪水事件[1]。另一方面,各个区域经历了几十年来最严重的热浪[2],干旱加剧,影响了中国广大地区的粮食生产、工业和基础设施。在欧洲一些国家,炎热的夏季已经变得越来越多,热浪席卷各处,而十年前情况并非如此。

    2020 年,全球气温比工业化前水平高出1.2 °C (IPCC)。到本世纪末(2100 年),气温上升预计将达到约 100%。乐观情景下比工业化前水平高出1.8 ° C,当前政策下比工业化前水平高出2.7 ° C(IPCC)。

    科学家们一致认为,到 2100 年,全球气温上升需要限制在比工业化前水平高1.5 °C的范围内,以防止气候系统发生不可逆转的变化(IPCC)。

    数据和方法

    本文通过 NASA过去 142 年的历史全球温度异常和NOAA的过去几十年二氧化碳全球浓度数据,基于 Python 中的 matplotlib 和 seaborn 包可视化数据。

    代码

    从 1880 年开始记录以来,全球年平均地表气温变化数据可从 NASA GISS 网站获取:https://data.giss.nasa.gov/gistemp/graphs_v4/

    同时文末也提供了本文的数据和代码。

    1. import pandas as pd
    2. df = pd.read_csv('data/graph.csv')
    3. #https://data.giss.nasa.gov/gistemp/graphs_v4/

    图片

     

    为了可视化的一致性,自定义了 matplotlib 的默认设置。

    1. import matplotlib.pyplot as plt
    2. #figure size and font size
    3. plt.rcParams["figure.figsize"= (106)
    4. plt.rcParams["font.size"= 14
    5. #grid lines
    6. plt.rcParams["axes.grid"= True
    7. plt.rcParams["axes.grid.axis"= "y"
    8. #Setting up axes
    9. plt.rcParams['axes.spines.bottom'= True
    10. plt.rcParams['axes.spines.left'= False
    11. plt.rcParams['axes.spines.right'= False
    12. plt.rcParams['axes.spines.top'= False
    13. plt.rcParams['axes.linewidth'= 0.5
    14. #Ticks
    15. plt.rcParams['ytick.major.width'= 0
    16. plt.rcParams['ytick.major.size'= 0

    首先进行一个简单的绘制。

    1. import numpy as np
    2. fig, ax = plt.subplots()
    3. df["Annual Mean"].plot(ax = ax, c = "black", marker = "s")
    4. df["Lowess Smoothing"].plot(ax = ax, c = "red")
    5. = df.index.tolist()
    6. = df["Annual Mean"].tolist()
    7. # Define the 95% confidence interval
    8. ci = np.mean(y) + 1.96 * np.std(y) / np.sqrt(len(y))
    9. plt.fill_between(x, y-ci, y+ci,
    10.              color = "gray",
    11.                 alpha = 0.25,
    12.                 label = "LSAT+SST Uncertainty")
    13. ax.axhline(y = 0, linestyle = "--", color = "black")
    14. plt.legend(loc = "upper left")
    15. plt.ylabel("Temperature anomaly w.r.t. 1951-80 mean (°C)")
    16. plt.title("Global surface air temperature change estimates based on land and ocean data")
    17. plt.show()

    图片

    黑线表示全球年平均地表气温相对于 1951-1980 年平均值的变化。红线是五年最低平滑线。

    温度异常数据存在不确定性,这些不确定性源于测量、台站记录和土地覆盖变化导致的系统偏差。灰色阴影区域代表 95% 置信区间

    本图也类似于IPCC的一贯表达方式。

    本图也类似于IPCC的一贯表达方式。

    图片

    接下来绘制一个简单的条形图。

    1. df["Annual Mean"].plot(kind = "bar")
    2. years = np.arange(1880202220)
    3. plt.xticks(ticks = np.arange(014220), labels = years)
    4. plt.title("Global Surface Temperature relative to 1950 to 1980 Mean")
    5. plt.ylabel("Temperature Anomaly (°C)")
    6. plt.show()

    图片

    现在的条形图很单调,我们想添加温度的映射,首先查看色卡:

    1. my_cmap = plt.get_cmap("coolwarm")
    2. my_cmap

    图片

     

    映射色卡,这一步功能用seaborn则很方便:(只需要一行代码)

    1. import seaborn as sns
    2. sns.barplot(x = df.index, y = df["Annual Mean"],
    3.             palette = "coolwarm")
    4. years = np.arange(1880202220)
    5. plt.xticks(ticks = np.arange(014220), labels = years)
    6. plt.title("Global Surface Temperature relative to 1950 to 1980 Mean")
    7. plt.ylabel("Temperature Anomaly (°C)")
    8. plt.show()

    图片

    如果使用matplotlib,相对麻烦,思路是用 lambda 匿名函数将温度缩放在 0 1之间。所选颜色图 (coolwarm)my_cmap包含 255 种组合,其中my_cmap([0])指的是蓝色,my_cmap([1])指的是红色。其次,缩放值为每个条纹选择这些颜色y

    1. = df['Year'].tolist()
    2. = df["Annual Mean"].values.tolist()
    3. #rescale y between 0 (min) and 1 (max)
    4. rescale = lambda y: (y - np.min(y)) / (np.max(y) - np.min(y))
    5. plt.bar(x, y, color = my_cmap(rescale(y)), width = 0.8)
    6. years = np.arange(1880202220)
    7. plt.xticks(ticks = years, labels = years)
    8. plt.title("Global surface temperature relative to 1951-1980 Mean")
    9. plt.ylabel("Temperature Anomaly (°C)"); plt.xlabel("Year")
    10. plt.show()

    图片

    两张可视化是一致的,接下来想创建升温条带,这里使用PatchCollection功能,这个函数让我们能自定义各种图案。

    首先将年平均气温异常读取为 pandas anomaly。然后用PatchCollection为 1880 年至 2021 年间的每一年创建了统一的条纹。数据anomaly相当于 PatchCollection col

    1. from matplotlib.collections import PatchCollection
    2. from matplotlib.patches import Rectangle
    3. #matplotlib.patches.Rectangle
    4. anomaly = df["Annual Mean"]
    5. fig = plt.figure(figsize = (101.5))
    6. ax = fig.add_axes([0011])
    7. #turn the x and y-axis off
    8. ax.set_axis_off()
    9. #create a collection with a rectangle for each year
    10. col = PatchCollection([
    11.                     Rectangle((y, -1),  #xy
    12.                     1,       #width
    13.                     2        #height
    14.                      ) for y in np.arange(18802022)])
    15. #use the anomaly data for colormap
    16. col.set_array(anomaly)
    17. #apply the colormap colors
    18. cmap = plt.get_cmap("coolwarm")
    19. col.set_cmap(cmap)
    20. ax.add_collection(col)
    21. #average global temperature line
    22. ax.axhline(0, linestyle = "--", color = "white")
    23. df.plot(ax = ax, linestyle = "-", color = "black", legend = False)
    24. #add title and text
    25. ax.set_title("Warming Stripes (1880-2021)", loc = "center", y = 0.75)
    26. ax.text(x = 1880, y = -1, s = "1880")
    27. ax.text(x = 2022, y = -1, s = "2021")
    28. ax.set_ylim(-12)
    29. ax.set_xlim(18702030)

    图片

    全球温度变暖有多方面原因,CO2温室气体是一个主要的原因:截至 2016 年,二氧化碳 (CO2) 占全球温室气体排放量的四分之三,其次是甲烷 (CH₄,17%)、一氧化二氮 (N2O,6%) ,可参考相关报告。

    1. import matplotlib.pyplot as plt
    2. gases = ["CO$_2$""CH$_4$""N$_2$O""F-gases"]
    3. warming_potential = [1253001000]
    4. text_height = [i*1.2 for i in warming_potential]
    5. text = ["1""25""300""1000+"
    6. volume = [74.417.36.22.1]
    7. colors = ["brown""darkslategray""darkgray""purple"]
    8. fig, (ax1, ax2= plt.subplots(12)
    9. ax1.bar(gases, warming_potential, color = colors)
    10. for i, height, word in zip(range(4), text_height, text):
    11.     ax1.text(x = i * 0.9, y = height, s = word)
    12. ax1.set_yscale("log")
    13. ax1.set_title("Global warming potential (GWP)\n by gas over 100-year timescale", y = 1)
    14. ax1.spines.top.set_visible(False)
    15. ax1.spines.right.set_visible(False)
    16. autopct = lambda p:f'{p:.1f}%'
    17. ax2.pie(x = volume, radius = 1, startangle = 90, labels = gases,
    18.         autopct = autopct, pctdistance = 0.8, colors = colors, textprops = {"color":"white"})
    19. ax2.legend(labels = gases, bbox_to_anchor = (0.90.8), ncol = 1)
    20. ax2.set_title("Atmospheric composition of global \nGHG emissions", y = 1.1)
    21. plt.tight_layout()
    22. plt.show()

    图片

    最后将二氧化碳与温度结合在一个图里,创建双y轴图像,来完成本文的收尾~

    1. co2_annual = pd.read_csv('data/co2_annmean_mlo.csv')
    2. # https://gml.noaa.gov/ccgg/trends/global.html#global
    3. rescale = lambda y: (y - np.min(y)) / (np.max(y) - np.min(y))
    4. fig, ax1 = plt.subplots()
    5. df_temp = df[df['Year'>= 1959]
    6. = df_temp['Year'].tolist()
    7. = df_temp["mean"].values.tolist()
    8. ax1.bar(x, y, color = my_cmap(rescale(y)), width = 0.8)
    9. ax1.set_ylabel("Temperature anomaly \n relative to 1951-80 mean (°C)", color = "red")
    10. ax1.tick_params(axis='y', color='red', labelcolor='red')
    11. ax1.grid(False)
    12. #Add twin axes
    13. ax2 = ax1.twinx()
    14. ax2.plot(x, co2_annual['mean'], color = "black", marker = "o", markersize = 4)
    15. ax2.set_ylabel("CO$_2$ (ppm)")
    16. ax2.grid(False)
    17. ax2.tick_params(axis='y')
    18. for pos in ["top"]:
    19.     ax1.spines[pos].set_visible(False)
    20.     ax2.spines[pos].set_visible(False)
    21. plt.grid()
    22. plt.title("Global temperature anomaly and atmospheric CO$_2$ emissions concentration\n (1959-2021)",
    23.          pad = 20)
    24. plt.show()

    图片

    reference

    1. https://www.nytimes.com/2022/09/14/world/asia/pakistan-floods.html

    2. https://multimedia.scmp.com/infographics/news/china/article/3190803/china-drought/index.html

  • 相关阅读:
    Unity三种物体溶解方法
    C++中函数原型和函数定义
    javab每日一题:在spring里有哪些常用注解?
    字节跳动面试——算法
    2023江苏科技大学计算机考研信息汇总
    本地部署大语言模型
    【PyTorch实战】用PyTorch实现基于神经网络的图像风格迁移
    Jira的原理及应用详解(二)
    vue 实现前台用户登录
    python:Möller–Trumbore射线三角面相交算法
  • 原文地址:https://blog.csdn.net/2301_77413856/article/details/133353271