Pollution Data Visualization Project in Python

Data Science project 07

Pollution Data Visualization Project in Python

Build a complete data visualization on pollution data workflow with reproducible Python code, traceable calculations, validation checks, and honest limitations.

Explore Data Science training in VizagView all project ideas

Analysis question

How can noisy daily measurements be converted into a readable, honest two-series trend chart?

Dataset

A 180-day synthetic series of PM2.5 and nitrogen-dioxide-like measurements in demonstration units.

Requirements

  • Python 3.10 or later
  • A terminal or command prompt
  • python -m pip install numpy pandas matplotlib
  • About 45-60 minutes to build and review

Method and data checks

Sort observations by date, calculate separate seven-day rolling averages, draw labelled lines with a shared axis, add a legend and grid, and save a high-resolution PNG.

  • The title says the measurements are synthetic
  • Units are labelled as demonstration units
  • Both series use the same smoothing window
  • The figure is closed after saving to avoid resource leaks

Complete Python code

Save the program as ds_pollution_visualization.py. The dataset generator or loader, analysis functions, output, and reproducibility controls are included.

"""Create a readable pollution trend chart from synthetic measurements."""

from __future__ import annotations

from pathlib import Path
import numpy as np
import pandas as pd
import matplotlib

matplotlib.use("Agg")
import matplotlib.pyplot as plt


def make_demo_pollution(days: int = 180, seed: int = 42) -> pd.DataFrame:
    rng = np.random.default_rng(seed)
    dates = pd.date_range("2025-01-01", periods=days)
    x = np.arange(days)
    pm25 = np.clip(45 + 13 * np.sin(2 * np.pi * x / 30) + rng.normal(0, 7, days), 2, None)
    no2 = np.clip(28 + 7 * np.sin(2 * np.pi * (x + 5) / 14) + rng.normal(0, 4, days), 1, None)
    return pd.DataFrame({"date": dates, "pm25": pm25, "no2": no2})


def create_chart(data: pd.DataFrame, output: str | Path = "pollution_trends.png") -> Path:
    plot = data.copy().sort_values("date")
    plot["pm25_7d"] = plot["pm25"].rolling(7, min_periods=1).mean()
    plot["no2_7d"] = plot["no2"].rolling(7, min_periods=1).mean()
    fig, ax = plt.subplots(figsize=(10, 5.2))
    ax.plot(plot["date"], plot["pm25_7d"], label="PM2.5, 7-day average", linewidth=2.2)
    ax.plot(plot["date"], plot["no2_7d"], label="NOâ‚‚, 7-day average", linewidth=2.2)
    ax.set(title="Synthetic pollution measurements", xlabel="Date", ylabel="Demo concentration units")
    ax.grid(alpha=0.25)
    ax.legend()
    fig.tight_layout()
    path = Path(output)
    fig.savefig(path, dpi=150)
    plt.close(fig)
    return path


def main() -> None:
    path = create_chart(make_demo_pollution())
    print(f"Saved {path.resolve()}")
    print("Synthetic teaching measurements — not a public-health data source.")


if __name__ == "__main__":
    main()

Run the project

  1. Create and activate a virtual environment.
  2. Install dependencies with python -m pip install numpy pandas matplotlib.
  3. Run python ds_pollution_visualization.py.
  4. Reconcile row counts and totals before interpreting patterns.
  5. Read the limitations before substituting any real dataset.

Expected analytical output

A reviewable pollution_trends.png chart with two labelled seven-day-average lines.

Interpretation and responsible-use limits

The generated measurements and units are not environmental-monitoring evidence or public-health guidance. Real comparisons need calibrated sensors, comparable units, quality flags, and authoritative thresholds.

Ways to extend the project

Load an open government dataset, show missingness, add uncertainty bands, include a raw-data view, use accessible colours, and annotate documented events.

Continue learning Data Science

Try the next project, return to the Softenant project library, or explore the Data Science course in Vizag for guided data cleaning, analysis, visualisation, and portfolio feedback.