利用Python可视化全球二氧化碳排放

大家好,近几年碳的问题一直很火,那么关于碳数据的收集就比较重要,刚好前不久见到一个全球实时碳数据的网站,里面包含碳的数据,网站包含一些主要国家碳排放数据。网站链接:全球实时碳数据 Carbon Monitor

关于我们如何绘制地图,刚好有个国外大神Adam Symington画了很多好看的地图,其中就有二氧化碳排放的地图。我们借鉴他的思路,选择自己想要表达的效果。接下来,我们开始对数据进行可视化。

一.读取二氧化碳排放数据


#!/usr/bin/env python
# -*- coding: utf-8 -*-
# author:GuaGua
# datetime:2022/5/18 11:15
# env:python3.8
import pandas as pd
#读取数据
data= pd.read_csv("v50_CO2_excl_short-cycle_org_C_2018.txt", delimiter=';')
data

lat

lon

emission

0

88.1

-50.7

11.0301

1

88.1

-50.6

15.7066

2

88.1

-50.5

19.1943

3

88.1

-50.4

22.0621

4

88.1

-50.3

24.5536

...

...

...

...

2191880

-77.8

166.5

11459.2000

2191881

-77.8

166.6

694.4980

2191882

-77.9

166.3

2133.1000

2191883

-77.9

166.4

1389.0000

2191884

-77.9

166.5

7887.5100

2191885 rows × 3 columns

二.可视化画图


#首先进行简单可视化
import matplotlib.pyplot as plt
#设置字体
plt.rc('font',family='Times New Roman') 
fig = plt.figure(figsize=(10,5))
pic=plt.scatter(data['lon'], data['lat'],c=data['emission'], s=0.05,  edgecolors='none')
plt.colorbar(pic)
plt.show()

三.对图形进行优化


#对数颜色映射的一个小例子,帮助大家理解下面颜色映射,为后续做好准备
import numpy as np
import matplotlib.pyplot as plt
from matplotlib import colors
#首先构造一个指数函数
x=np.linspace(0,10,100)
y=np.linspace(0,10,100)
matX=np.matrix(np.exp(2*x))
matY=np.matrix(np.exp(3*y)).T
Z=np.array(matY @ matX)
fig, ax = plt.subplots(3, 1,figsize=(10,8))
pcm=ax[0].contourf(x,y,Z,cmap='jet',levels=100)
fig.colorbar(pcm,ax=ax[0])
#matplotlib.colors.LogNorm(vmin=None, vmax=None, clip=False)
#将给定值对应于对数化的0-1的范围,其中vmin和vmax定义的是用来scale的值的区间,如果这两个值没有给,那么默认是最大值和最小值。
#我们可以看见绝大部分都是蓝色,只有尖角的一小部分有红色,默认的颜色分割方式把它等距的分割开,这个情况下,我们使用对数尺度的颜色映射
pcm=ax[1].contourf(x,y,Z,cmap='jet',norm=colors.LogNorm())
fig.colorbar(pcm,ax=ax[1])
logmax=np.log10(Z.max())
logmin=np.log10(Z.min())
#按照对数均匀生成100个等级。三种颜色映射对比
lvls=np.logspace(logmin,logmax,100)
pcm=ax[2].contourf(x,y,Z,cmap='jet',levels=lvls,norm=colors.LogNorm())
fig.colorbar(pcm,ax=ax[2])
plt.show()

#原始颜色对数映射。对比更加明显
from matplotlib import colors
fig = plt.figure(figsize=(10,5))
pic = plt.scatter(data['lon'], data['lat'],c=data['emission'],s=0.05, edgecolors='none',  norm=colors.LogNorm())
plt.colorbar(pic)
plt.show()

由于matplotlib提供的颜色映射表是有限的,所以我们还需要借助外部的库包提供额外的颜色映射表。大气科学与海洋科学常用的外部颜色库包常为cmaps,cmaps库包是将NCL平台的颜色移植到python。


import cmaps
import numpy as np
import inspect
import matplotlib.pyplot as plt
import matplotlib
matplotlib.rc('text', usetex=False)
#展示所有的颜色映射
def list_cmaps():
    attributes = inspect.getmembers(cmaps, lambda _: not (inspect.isroutine(_)))
    colors = [_[0] for _ in attributes if
              not (_[0].startswith('__') and _[0].endswith('__'))]
    return colors


if __name__ == '__main__':
    color = list_cmaps()

    a = np.outer(np.arange(0, 1, 0.001), np.ones(10))
    plt.figure(figsize=(20, 20))
    plt.subplots_adjust(top=0.95, bottom=0.05, left=0.01, right=0.99)
    ncmaps = len(color)
    nrows = 8
    for i, k in enumerate(color):
        plt.subplot(nrows, ncmaps // nrows + 1, i + 1)
        plt.axis('off')
        plt.imshow(a, aspect='auto', cmap=getattr(cmaps, k), origin='lower')
        plt.title(k, rotation=90, fontsize=10)
        plt.title(k, fontsize=10)
    plt.savefig('colormaps.png', dpi=300)

import cmaps   
#调整颜色,根据上面的色带选择自己喜欢的颜色
fig, ax = plt.subplots(2, 1,figsize=(10,10))
#在使用cmaps时,只需引入库包,然后填写颜色名称即可,选用两种色带进行对比看看
cmap1=cmaps.BlueWhiteOrangeRed
cmap2=cmaps.MPL_RdYlGn_r
pic = ax[0].scatter(data['lon'], data['lat'],c=data['emission'],s=0.05, edgecolors='none',  norm=colors.LogNorm(),cmap=cmap1)
fig.colorbar(pic,ax=ax[0])
pic = ax[1].scatter(data['lon'], data['lat'],c=data['emission'],s=0.05, edgecolors='none',  norm=colors.LogNorm(),cmap=cmap2)
fig.colorbar(pic,ax=ax[1])
plt.show()

四.对图形进行投影


import geopandas as gpd
from shapely.geometry import Point
geometry = [Point(xy) for xy in zip(data['lon'], data['lat'])]# # 需要修改为对应的经纬度字段
geodata = gpd.GeoDataFrame(data, crs="EPSG:4326", geometry=geometry)# 指定坐标系
geodata

import matplotlib.pyplot as plt                                          
import cartopy.crs as ccrs                                               
from matplotlib import cm
from matplotlib.colors import ListedColormap
import matplotlib as mpl   
import matplotlib.ticker as mticker
from cartopy.mpl.gridliner import LONGITUDE_FORMATTER, LATITUDE_FORMATTER
plt.rc('font',family='Times New Roman') 
fig=plt.figure(figsize=(6,4),dpi=200)
#ax首先得定义坐标系
ax=fig.add_axes([0,0,1,1],projection=ccrs.PlateCarree())
ax = geodata.plot(ax=ax, column='emission', transform=ccrs.PlateCarree(),
                  cmap=cmap1, norm=colors.LogNorm(), s=0.05, edgecolors='none')
ax.set_title('2018 CO$_2$ Emissions',fontsize=15,fontweight ='bold')
#添加文本信息
text = ax.text(0.0, 0.02, "By GuaGua",
              size=10,
              fontweight ='bold',
              transform = ax.transAxes)
#gridlines设置经纬度标签
gl=ax.gridlines(draw_labels=True,linestyle=":",linewidth=0.3,color='red')
gl.top_labels=False #关闭上部经纬标签                                  
gl.right_labels=False#关闭右边经纬标签  
gl.xformatter = LONGITUDE_FORMATTER  #使横坐标转化为经纬度格式            
gl.yformatter = LATITUDE_FORMATTER                                        
gl.xlocator=mticker.FixedLocator(np.arange(-180,180,20))      
gl.ylocator=mticker.FixedLocator(np.arange(-90,90,20)) 
#修改经纬度字体大小 
gl.xlabel_style={'size':8, 'weight': 'bold'}                            
gl.ylabel_style={'size':8, 'weight': 'bold'}

#使用Robinson投影,默认中央子午线为中心
import cartopy.crs as ccrs 
import matplotlib.ticker as mticker
import matplotlib.pyplot as plt
fig, ax = plt.subplots(figsize=(10,5), subplot_kw={'projection': ccrs.Robinson()})
ax = geodata.plot(ax=ax, column='emission', transform=ccrs.PlateCarree(),
                  cmap=cmap2, norm=colors.LogNorm(), s=0.05, edgecolors='none')
#添加文本信息
text = ax.text(0.0, 0.02, "By GuaGua",
              size=10,
              fontweight ='bold',
              transform = ax.transAxes)
#添加格网
g2=ax.gridlines(linestyle='--',draw_labels=True,linewidth=1,alpha=0.5)
g2.xformatter = LONGITUDE_FORMATTER  # x轴设为经度的格式
g2.yformatter = LATITUDE_FORMATTER  # y轴设为纬度的格式
#设置经纬度网格的间隔
g2.xlocator = mticker.FixedLocator(np.arange(-180, 180, 60))
g2.ylocator = mticker.FixedLocator(np.arange(-90, 90, 30))
#修改经纬度字体大小 
g2.xlabel_style={'size':10,'weight': 'bold'}                            
g2.ylabel_style={'size':10,'weight': 'bold'}
#添加标题
ax.set_title('2018 CO$_2$ Emissions',
              fontsize=15,
              pad=20,
              fontweight ='bold')
plt.show()

五.色彩映射


#发现前面颜色对比不够明显,我们重新设置colorbar,截取部分colormap
from matplotlib import cm
from matplotlib.colors import ListedColormap
import numpy as np
import matplotlib as mpl   
import matplotlib.pyplot as plt
fig=plt.figure(figsize=(10,8),dpi=300)
ax1=fig.add_axes([0,0,1,0.05])                                                 
ax2=fig.add_axes([0,0.1,1,0.05])  
ax3=fig.add_axes([0,0.2,1,0.05])  
#第一个 
our_cmap = cm.get_cmap('afmhot', 11)
newcolors = our_cmap(np.linspace(0, 1, 11))#分片操作,生成0到1的11个数据间隔的数组   
our_cmap = ListedColormap(newcolors[::1])#重构为新的colormap
#第二个                                    
newcolors_1=cmap2(np.linspace(0,1,11))#分片操作,生成0到1的11个数据间隔的数组                                  
newcmap=ListedColormap(newcolors_1[::1])  #重构为新的colormap
#第三个
newcolors_2=cmap1(np.linspace(0,1,11))#分片操作,生成0到1的11个数据间隔的数组                                  
newcmap2=ListedColormap(newcolors_2[::1])  #重构为新的colormap
###########################################
bounds = [0.0, 0.06, 6, 60, 600, 3000, 6000, 24000, 45000, 120000]
norm = colors.BoundaryNorm(bounds, our_cmap.N)#基于离散间隔创建颜色图
norm1 = colors.BoundaryNorm(bounds, newcmap.N)#基于离散间隔创建颜色图
norm2 = colors.BoundaryNorm(bounds, newcmap2.N)#基于离散间隔创建颜色图
fc1=fig.colorbar(mpl.cm.ScalarMappable(norm=norm,cmap=our_cmap),              
                cax=ax1,                                                      
                orientation='horizontal',   
                label='our cmap',
                ticks=bounds,                                                    
                extend='both')
fc2=fig.colorbar(mpl.cm.ScalarMappable(norm=norm1,cmap=newcmap),              
                cax=ax2,                                                      
                orientation='horizontal',   
                label='newcmap',
                ticks=bounds,                                                    
                extend='both')
fc3=fig.colorbar(mpl.cm.ScalarMappable(norm=norm2,cmap=newcmap2),              
                cax=ax3,                                                      
                orientation='horizontal',   
                label='newcmap2',
                ticks=bounds,                                                    
                extend='both')

fig, ax = plt.subplots(figsize=(10,5), subplot_kw={'projection': ccrs.Robinson()})
ax = geodata.plot(ax=ax, column='emission', transform=ccrs.PlateCarree(),
                  cmap=newcmap, norm=norm1, s=0.05, alpha=1, edgecolors='none')
#添加文本信息
text = ax.text(0.0, 0.02, "By GuaGua",
              size=10,
              fontweight ='bold',
              transform = ax.transAxes)
#添加格网
g3=ax.gridlines(linestyle='--',draw_labels=True,linewidth=1,alpha=0.5)
g3.xformatter = LONGITUDE_FORMATTER  # x轴设为经度的格式
g3.yformatter = LATITUDE_FORMATTER  # y轴设为纬度的格式
#设置经纬度网格的间隔
g3.xlocator = mticker.FixedLocator(np.arange(-180, 180, 60))
g3.ylocator = mticker.FixedLocator(np.arange(-90, 90, 30))
#修改经纬度字体大小 
g3.xlabel_style={'size':10,'weight': 'bold'}                            
g3.ylabel_style={'size':10,'weight': 'bold'}
#添加标题
ax.set_title('2018 CO$_2$ Emissions',
              fontsize=15,
              fontweight ='bold',
              pad=20)
plt.savefig('co2_emissions_noclorbar.png', dpi=300,bbox_inches='tight')
plt.show()

六.添加图例


fig, ax = plt.subplots(figsize=(10,5),subplot_kw={'projection': ccrs.Robinson()})
ax = geodata.plot(ax=ax, column='emission', transform=ccrs.PlateCarree(),
                  cmap=newcmap, norm=norm1, s=0.05, alpha=1, edgecolors='none')
#添加文本信息
text= ax.text(0.0, 0.02, "By GuaGua",
              size=10,
              fontweight ='bold',
              transform = ax.transAxes)
#添加格网
g3=ax.gridlines(linestyle='--',draw_labels=True,linewidth=1,alpha=0.5)
g3.xformatter = LONGITUDE_FORMATTER  # x轴设为经度的格式
g3.yformatter = LATITUDE_FORMATTER  # y轴设为纬度的格式
#设置经纬度网格的间隔
g3.xlocator = mticker.FixedLocator(np.arange(-180, 180, 60))
g3.ylocator = mticker.FixedLocator(np.arange(-90, 90, 30))
#修改经纬度字体大小 
g3.xlabel_style={'size':10,'weight': 'bold'}                            
g3.ylabel_style={'size':10,'weight': 'bold'}
#添加标题
ax.set_title('2018 CO$_2$ Emissions',
              fontsize=15,
              fontweight ='bold',
              pad=20)
#设置图例
fig = ax.get_figure()
cax = fig.add_axes([0.36, 0.16, 0.33, 0.01])
sm = plt.cm.ScalarMappable(cmap=newcmap, norm=norm1)
cb = fig.colorbar(sm, cax=cax, orientation="horizontal", pad=0.2, format='%.1e',
                  ticks=[0.03, 3, 33, 330, 1800, 4500, 15000, 34500, 82500],
                  drawedges=True)
cb.outline.set_visible(False)
cb.ax.tick_params(labelsize=6, width=0.5, length=0.5)
cbytick_obj = plt.getp(cb.ax, 'xticklabels' ) 
plt.setp(cbytick_obj)
cb.ax.set_xlabel('CO$_2$ Tons/Year', fontsize=6,  labelpad=-20)
# plt.savefig('co2_emissions.jpg', dpi=300, bbox_inches='tight')
plt.show()

  • 7
    点赞
  • 50
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

python慕遥

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值