How to Visualize Air‑Quality Data in Python with Matplotlib: A Step‑by‑Step Guide
This article walks through reading Excel air‑quality data with pandas and creating four‑panel visualizations of AQI, pollutants, temperature and humidity using Matplotlib, providing complete code and tips for handling common plotting pitfalls.
Introduction
The author received a question in a Python community about visualizing air‑quality data and shares the solution here.
Solution Overview
The approach uses pandas to load an Excel file, extracts relevant columns, and creates a 4 × 1 subplot layout with Matplotlib. Each subplot displays a different metric (AQI, PM2.5, PM10, SO₂, CO, NO₂, O₃, temperature, humidity) and includes twin‑axis plots where needed.
Key Code
# -*- coding: UTF-8 -*-
# Development time: 2023/3/12 14:57
import matplotlib.pyplot as plt
import pandas as pd
import numpy as np
# Load data from Excel (adjust the path to your file)
Data = pd.read_excel(r"H:\小论文\小论文\白城空气质量气象数据\空气质量数据\白城2015.10.26.xlsx")
X1 = Data.Date
Y1 = Data.AQI
Y2 = Data["PM2.5"]
Y3 = Data.PM10
Y4 = Data.SO2
Y5 = Data.CO
Y6 = Data.NO2
Y7 = Data.O3
Y8 = Data.温度
Y9 = Data.相对湿度百分比
# Create a 4x1 figure
f, ax = plt.subplots(4, 1, figsize=(15, 10))
plt.subplots_adjust(wspace=0, hspace=0)
# ----- Subplot 1: AQI, PM2.5, PM10 -----
ax1 = plt.subplot(411)
ax1.set_ylim(bottom=0, top=520)
ax1.plot(X1, Y1, color='black', marker='o', markeredgecolor='black', linewidth=0.5, markerfacecolor='yellow', label='AQI')
ax1.set_ylabel('AQI')
ax1.legend(ncol=1, frameon=False)
ax1_twin = ax1.twinx()
ax1_twin.plot(X1, Y2, color='black', marker='o', markeredgecolor='black', linewidth=0.5, markerfacecolor='lime', label='PM$_2$$_5$')
ax1_twin.plot(X1, Y3, color='black', marker='o', markeredgecolor='black', linewidth=0.5, markerfacecolor='red', label='PM$_{10}$')
ax1_twin.set_ylabel('PM$_2$$_5$/PM$_{10}$ (µg/m³)')
ax1_twin.legend(bbox_to_anchor=(0.92, 1), frameon=False, ncol=3)
ax1_twin.set_ylim(bottom=0, top=800)
# ----- Subplot 2: SO₂ and CO -----
ax2 = plt.subplot(412)
ax2.plot(X1, Y4, color='black', marker='o', markeredgecolor='black', linewidth=0.5, markerfacecolor='aqua', label='SO$_2$')
ax2.set_ylabel('SO$_2$ (µg/m³)')
ax2.legend(frameon=False)
ax2.set_ylim(bottom=0, top=70)
ax2.tick_params(axis='x', labelbottom=False)
ax2_twin = ax2.twinx()
ax2_twin.plot(X1, Y5, color='black', marker='o', markeredgecolor='black', linewidth=0.5, markerfacecolor='blue', label='CO')
ax2_twin.set_ylabel('CO (µg/m³)')
ax2_twin.legend(bbox_to_anchor=(0.92, 0.99), frameon=False)
ax2_twin.set_ylim(0, 2.8)
# ----- Subplot 3: NO₂ and O₃ -----
ax3 = plt.subplot(413)
ax3.set_ylim(bottom=0, top=88)
ax3.plot(X1, Y6, color='black', marker='o', markeredgecolor='black', linewidth=0.5, markerfacecolor='yellow', label='NO$_2$')
ax3.set_ylabel('NO$_2$ (µg/m³)')
ax3.legend(bbox_to_anchor=(0.92, 1), frameon=False)
ax3_twin = ax3.twinx()
ax3_twin.plot(X1, Y7, color='black', marker='o', markeredgecolor='black', linewidth=0.5, markerfacecolor='lime', label='O$_3$')
ax3_twin.set_ylabel('O$_3$ (µg/m³)')
ax3_twin.legend(bbox_to_anchor=(1, 1), frameon=False)
ax3_twin.set_ylim(bottom=0, top=119)
# ----- Subplot 4: Temperature and Humidity -----
ax4 = plt.subplot(414)
ax4.plot(X1, Y8, color='black', marker='o', markeredgecolor='black', linewidth=0.5, markerfacecolor='blue', label='温度')
ax4.set_ylabel('温度(℃)')
ax4.set_ylim(bottom=-8, top=14)
ax4.legend(bbox_to_anchor=(1, 1), frameon=False)
ax4_twin = ax4.twinx()
ax4_twin.plot(X1, Y9, color='black', marker='o', markeredgecolor='black', linewidth=0.5, markerfacecolor='red', label='湿度')
ax4_twin.set_ylabel('湿度(%)')
ax4_twin.set_ylim(0, 99)
ax4_twin.legend(bbox_to_anchor=(0.92, 1), frameon=False)
# Display the figure
plt.show()Result
The script produces a clear four‑panel figure showing air‑quality indices, pollutant concentrations, temperature and humidity over the selected dates, successfully answering the community member’s visualization request.
Conclusion
The author thanks the contributors who provided ideas and code, and reminds readers to share clean demo data and error screenshots when seeking help.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Python Crawling & Data Mining
Life's short, I code in Python. This channel shares Python web crawling, data mining, analysis, processing, visualization, automated testing, DevOps, big data, AI, cloud computing, machine learning tools, resources, news, technical articles, tutorial videos and learning materials. Join us!
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
