社区所有版块导航
Python
python开源   Django   Python   DjangoApp   pycharm  
DATA
docker   Elasticsearch  
aigc
aigc   chatgpt  
WEB开发
linux   MongoDB   Redis   DATABASE   NGINX   其他Web框架   web工具   zookeeper   tornado   NoSql   Bootstrap   js   peewee   Git   bottle   IE   MQ   Jquery  
机器学习
机器学习算法  
Python88.com
反馈   公告   社区推广  
产品
短视频  
印度
印度  
Py学习  »  Python

北京空气质量真的很差吗?Python绘制热力图一目了然

CDA数据分析师 • 4 年前 • 471 次点击  

作者:可以叫我才哥 

本文转自公众号:可以叫我才哥


今年3月北京6再次遭遇沙尘暴,大家一起被迫吃土!上次沙尘暴出现还是在2015年4月15日

记得那天早上起床,打开手机看到好多盆友发来的询问关怀“听说北京沙尘暴了,注意安全哦”,比心 ! 随后拉开窗帘,果然是漫天黄沙还伴随着大风,打开朋友圈满屏的银翼杀手末日的关键字。

其实,我们看看北京最近15个月空气质量热力图发现,大部分的时间空气质量还是不错的,良好与优秀居多

注意:绿色(50以下) 表示优秀,黄色(50-100)表示良好,橙色及其他属于污染。

北京最近15个月空气质量热力图

上面这张热力图是用Python绘制的,今天就来讲一讲是如何做出来的。

目录:

  • 0. 图赏

  • 1. 空气质量数据获取

  • 2. 数据预处理

  • 3. 热力图绘制

    • 3.1. seaborn的heatmap热力图

    • 3.2. plotly的热力图绘制

  • 4. 附

0. 图赏

鸟巢:

鸟巢

故宫角楼:

故宫角楼

大裤衩:

大裤衩

银翼杀手:

银翼杀手

我上班路上:

202103月15日早上10点上班路上

1. 空气质量数据获取

这里我们从akshare库的接口直接获取北京市历史空气质量数据

import akshare as ak

air_quality_hist_df = ak.air_quality_hist(city="北京", period="day", start_date="2020-01-01", end_date="2021-03-15")
air_quality_hist_df.head()
请求的数据预览

2. 数据预处理

由于绘制热力图x轴是日期(1-31),y轴是年月。因此我们需要对原数据进行宽表转化和一些简单的预处理。

注意:处理过程详情代码注释说明。

import pandas as pd

# 拷贝并进行索引重置
df = air_quality_hist_df[['aqi']].copy()
df.reset_index(inplace=True)
# 将time字段改为时间格式
df.time = pd.to_datetime(df.time)
# 新增年月字段,内容为 x年x月,如2021年3月,为字符串格式
df['年月'] = df.time.apply(lambda x:x.strftime('%Y{y}%m{m}').format(y="年",m="月" ))
# 新增日期字段,内容为 1-31
df['日期'] = df['time'].dt.day

# 做透视处理,将长表转化为宽表
data = pd.pivot(df,
                values='aqi',
                index='年月',
                columns='日期')
# 转化后部分月份不存在部分日期默认为nan值,需要转化为数字格式 float(无法转化为int)
data = data.astype('float')
# 按照 索引年月倒序排序
data.sort_index(ascending=False,inplace=True)

data.head()
处理后数据预览


3. 热力图绘制

这里我们介绍两种热力图绘制手法,其一是sns.heatmap(),其二是plotlyff.create_annotated_heatmap()

3.1. seaborn的heatmap热力图

import matplotlib.pyplot as plt
import matplotlib.colors as mcolors
import seaborn as sns

#设置全局默认字体 为 雅黑
plt.rcParams['font.family'] = ['Microsoft YaHei'
# 设置全局轴标签字典大小
plt.rcParams["axes.labelsize"] = 14  
# 设置背景
sns.set_style("darkgrid",{"font.family":['Microsoft YaHei''SimHei']})  
# 设置画布长宽 和 dpi
plt.figure(figsize=(18,8),dpi=100)
# 自定义色卡
cmap = mcolors.LinearSegmentedColormap.from_list("n",['#95B359','#D3CF63','#E0991D','#D96161','#A257D0','#7B1216']) 
# 绘制热力图
ax = sns.heatmap( data, cmap=cmap, vmax=300
                 annot=True# 热力图上显示数值
                 fmt='0.f'# 数值格式
                 linewidths=0.5,) 
ax.set_title( label='北京最近15个月空气质量AQI',fontdict = {'fontsize'16})
# 将x轴刻度放在最上面
ax.xaxis.set_ticks_position('top'
效果

3.2. plotly的热力图绘制

对于plotly来说,plotly.express可以直接将满足条件格式的dataframe数据用px.imshow()绘制,不过试了很久暂时没学会怎么方便的将数值显示在热力图上。找了半天发现plotly提供另外一种方式create_annotated_heatmap,专门用来显示数值。

px.imshow方法:

import plotly.express as px
# import plotly.graph_objs as go

fig = px.imshow(data,
               color_continuous_scale='Temps'
               color_continuous_midpoint= 75 ,
               range_color = [0,300],
               title = '北京最近15个月空气质量AQI',
               width=1200,
               height=711,
               )
fig.update_layout(xaxis=dict(tickmode='linear'), # x轴全部显示
                 )
fig.show()
px.imshow方法

create_annotated_heatmap方法:

以下重点介绍该方法

  • 由于绘图的时候 顺序和之前是反的,所以需要先进行顺序逆序调整;
  • 为了更好的根据aqi数值进行颜色分配,我们可以对数据进行分箱操作;
  • 为了让颜色和空气质量指数级别色卡一致,我们可以自定义颜色色卡;
  • 为了更好的在热力图上显示数值,需要将原来的float转化为int,nan转化为空字符。
# 数据分箱操作
data.sort_index(ascending=True,inplace=True)
bins = [0,50 ,100,150,200,300,999]
groups = [.1,.2,.3,.4,.5,.6]
data1 = data.apply(lambda x: pd.cut(x,bins,labels=groups))
data1.head()
数据预览
import plotly.figure_factory as ff
import numpy as np

x = list(data.columns)
y = list(data.index)
z = data1.values.tolist()
z_text = data3.fillna('').values.tolist() # data3 为初始未进行格式转化的透视宽表
# 自定义色卡
colorscale=[[0.0'rgb(0,153,102)'], [.1'rgb(211, 207, 99)'],
            [.3'rgb(255, 153, 51)'], [.4'rgb(204, 97, 51)'],
            [.5'rgb(102, 0, 153)'],[1.0'rgb(126, 0, 35)']]

fig = ff.create_annotated_heatmap(z, x=x, y=y, 
                                  annotation_text=z_text, 
                                  colorscale=colorscale,
                                 )
fig.update_layout(title ='北京最近15个月空气质量AQI',
                   width=1200,
                   height=711,
                 )
# 将x轴刻度放在最上面
fig.update_xaxes(side="top")
fig.show()
北京最近15个月空气质量AQI

4. 附

空气质量指数色卡对照表:

空气质量评级

matplotlib 热力图绘制参考

https://matplotlib.org/stable/gallery/images_contours_and_fields/image_annotated_heatmap.html

plotly元素周期表绘制案例:

元素周期表
# Add Periodic Table Data
symbol = [['H''''''''''''''''''''' '''''''''''''He'],
         ['Li''Be''''''''''''''''''''''B''C''N''O''F''Ne'],
         ['Na''Mg''''''''''''''''''''''Al''Si''P''S''Cl''Ar'],
         ['K''Ca''Sc''Ti''V''Cr''Mn''Fe''Co''Ni''Cu''Zn''Ga''Ge''As''Se''Br''Kr'],
         ['Rb ' 'Sr''Y''Zr''Nb''Mo''Tc''Ru''Rh''Pd''Ag''Cd''In''Sn''Sb''Te''I''Xe' ],
         ['Cs''Ba''''Hf''Ta''W''Re''Os''Ir''Pt''Au''Hg''Tl''Pb''Bi''Po''At''Rn' ],
         ['Fr''Ra''''Rf''Db''Sg''Bh''Hs''Mt''Ds''Rg''Cn''Uut''Fl''Uup''Lv''Uus''Uuo'],
         ['''''La''Ce''Pr''Nd''Pm''Sm''Eu' 'Gd''Tb''Dy''Ho''Er''Tm''Yb''Lu'''],
         ['''''Ac''Th''Pa''U''Np''Pu''Am''Cm''Bk''Cf''Es''Fm''Md''No''Lr''' ],
         [''''''''''''''''''''''''''''''''''''],
         ['''Alkali Metal''''''Transition Metal''''''Actinide''''''Semimetal''''''Halogen''''''''' ],
         ['''Alkaline Metal''''''Lanthanide''''''Basic Metal''''''Nonmetal''''''Noble Gas''''''''']]

element = [['Hydrogen''''''''''''''''''''''''''''''''''Helium'],
           ['Lithium''Beryllium''''''''''''''''''''''Boron''Carbon''Nitrogen''Oxygen''Fluorine''Neon'],
           ['Sodium''Magnesium''''''''''' '''''''''''Aluminium''Silicon''Phosphorus''Sulfur''Chlorine'' Argon'],
           ['Potassium'' Calcium'' Scandium'' Titanium'' Vanadium'' Chromium',  'Manganese''Iron''Cobalt''Nickel''Copper''Zinc''Gallium''Germanium''Arsenic''Selenium''Bromine''Krypton'],
           ['Rubidium''Strontium''Yttrium''Zirconium''Niobium''Molybdenum''Technetium''Ruthenium''Rhodium''Palladium''Silver''Cadmium''Indium''Tin''Antimony''Tellurium''Iodine''Xenon'],
           [' Cesium'' Barium''',  'Hafnium''Tantalum''Tungsten''Rhenium''Osmium''Iridium''Platinum''Gold''Mercury''Thallium''Lead' 'Bismuth''Polonium''Astatine''Radon'],
           [' Francium'' Radium''''Rutherfordium','Dubnium','Seaborgium','Bohrium','Hassium','Meitnerium','Darmstadtium','Roentgenium','Copernicium','Ununtrium','Ununquadium','Ununpentium','Ununhexium','Ununseptium','Ununoctium'],
           ['''',  'Lanthanum''Cerium''Praseodymium''Neodymium''Promethium''Samarium''Europium''Gadolinium''Terbium''Dysprosium''Holmium''Erbium''Thulium''Ytterbium''Lutetium'''],
           ['''''Actinium''Thorium''Protactinium''Uranium''Neptunium''Plutonium''Americium''Curium''Berkelium''Californium''Einsteinium','Fermium' ,'Mendelevium''Nobelium''Lawrencium''' ],
           ['' ''''''''''''''''''''''''''''''''''],
           [''''''''''''''''''''''''''''''''''''],
           ['''''''''''''''''''''''''''''''''''']]

atomic_mass = [[ 1.00794.0.0.0.0.0.0.0.0.0 .0.0.0.0.0.0.0,  4.002602],
     [ 6.9419.012182.0.0.0.0.0.0.0.0.0.0,  10.81112.010714.006715.999418.998403220.1797],
     [ 22.9897692824.3050.0.0.0.0.0.0.0.0.0.0,  26.981538628.085530.97376232.06535.45339.948],
     [ 39.098340.07844.95591247.86750.941551.996154.93804555.84558.93319558.693463.54665.3869.72372.6474.9216078.9679.90483.798 ],
     [ 85.467887.6288.9058591.22492.9063895.9698101.07102.90550106.42107.8682112.411114.818118.710121.760127.60126.90447131.293],
     [ 132.9054519137.327.0178.49180.94788183.84186.207190.23192.217195.084196.966569200.59204.3833207.2208.98040209210222],
     [223226.0267268271272270276281280285284289288293'unknown'294],
     [.0.0138.90547140.116140.90765144.242145 150.36151.964157.25158.92535162.500164.93032167.259168.93421173.054174.9668.0],
     [.0.0227232.03806231.03588238.02891237244243247247251252257258259262.0],
     [.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0],
     [.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0 .0.0],
     [.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0]]

z = [[.8.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.01.],
     [.1.2.0.0.0.0.0.0.0.0.0.0.7.8.8.8.91.],
     [.1.2.0.0.0.0 .0.0.0.0.0.0.6.7.8.8.91],
     [.1.2.3.3.3.3.3.3.3.3.3.3.6.7.8.8.91.],
     [.1.2.3.3.3.3.3.3.3.3.3.3.6.6.7.7.91.],
     [.1.2.4.3.3.3.3.3.3.3.3.3.6.6.6.7 .91.],
     [.1.2.5.3.3.3.3.3.3.3.3.3.6.6.6.6.91.],
     [.0.0.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.0],
     [.0.0.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.0],
     [.0.0.0.0.0.0 .0.0.0.0.0.0.0.0.0.0.0.0],
     [.1.1.1.3.3.3.5.5.5.7.7.7.9.9.9.0.0.0],
     [.2.2.2.4.4.4.6.6.6.8.8.81.1.1..0.0.0]]

# Display element name and atomic mass on hover
hover=[]
for x in range(len(symbol)):
    hover.append([i + '
'
 + 'Atomic Mass: ' + str(j)
                      for i, j in zip(element[x], atomic_mass[x])])

# Invert Matrices
symbol = symbol[::-1 ]
hover = hover[::-1]
z = z[::-1]

# Set Colorscale
colorscale=[[0.0'rgb(255,255,255)'], [.2'rgb(255, 255, 153)'],
            [.4'rgb(153, 255, 204)'], [.6'rgb(179, 217, 255)'],
            [.8'rgb(240, 179, 255)'],[1.0'rgb(255, 77, 148)']]

# Make Annotated Heatmap
fig = ff.create_annotated_heatmap(z, annotation_text=symbol, text=hover,
                                 colorscale=colorscale, font_colors=['black'], hoverinfo='text')
fig.update_layout(title_text='Periodic Table')
fig.show()
以上就是本次全部内容,演示代码 ipynb 文件:
https://pan.baidu.com/s/1iR8E8OAJ0KCm5Cw840Ellg 
提取码:0316
如果文章对你有帮助,欢迎转发/点赞/收藏~


 

推荐阅读


 

CDA课程咨询

Python社区是高质量的Python/Django开发社区
本文地址:http://www.python88.com/topic/114180
 
471 次点击