IT 544 Data Visualization · Walsh College · Winter 2025

Air Quality Visual Analysis

My plan for analyzing U.S. pollution data (trends, seasonality, hot days and picking the right chart for each audience) rebuilt as a live workbench on a public daily ozone dataset.

Data visualizationTime seriesSeasonalityRegressionMissing dataPython (pandas, Matplotlib) plan
SituationU.S. pollution data means different things to policy, health and operations audiences.
TaskShow trends, seasonality and hot days so each audience can act on the same data.
ActionBuilt time-series, seasonal and driver views on a public daily ozone dataset, choosing the chart per audience.
ResultOne dataset now reads correctly for three audiences, and the workbench reruns it live.
…daily records, May to Sep 1973
…days with no ozone reading
…mean ozone, observed days
…correlation of ozone with temperature

Live demo

One switch controls missing data for everything below. Watch which results move and which do not.

Dataset substitution

My final project planned visual analysis of the Kaggle U.S. Pollution dataset (about 1.4 million rows of PM2.5, NO2, O3, CO and SO2 readings by city, 2000 to 2016). That file is not bundled here, so this page re-creates the same workflow on R's public airquality dataset: 153 days of ozone and weather readings for New York, May to September 1973. The methods carry over; the numbers describe New York in 1973, not my Kaggle data.

Chart type

Ozone vs weather, with live regression

Ozone exceedance days

… days above the threshold

Drop missing daysImpute month mean

Illustrative only: 70 ppb is the level of today's EPA 8-hour ozone standard, but these readings are 1 pm to 3 pm averages, so the count is not a regulatory exceedance count.

How the missing-data choice changes the answers

Results

Computed from the observed readings (missing days dropped) unless the chart says otherwise.

Seasonality: ozone by month

Mean ozoneMedian ozone

What drives ozone: correlation with each weather variable

Drop missing daysImpute month mean

How it works

  1. Frame the question and the audience. My proposal starts from who reads the chart: policymakers, environmental groups and city planners need different views of the same pollution data.
  2. Load and profile. Read the table with pandas, check each column's coverage and flag gaps before charting (here, 37 of 153 ozone readings are missing).
  3. Decide how to treat missing values. Dropping incomplete days keeps only real readings; month-mean imputation keeps every day but invents values. The demo shows both side by side.
  4. Chart trend, seasonality and hot days. Line for the daily trend, monthly bars for seasonality, box plots for spread and a calendar heatmap for which days were worst, the single-site version of my hotspot map.
  5. Relate pollution to drivers. Fit a simple linear regression of ozone on temperature, wind and sunlight as the baseline model my plan describes before Random Forest and ARIMA.

My document also outlines Random Forest and ARIMA models on the Kaggle file; those results are not reproduced here because that data is not available to this page.

Data

Preview (first 10 rows; blank = missing)

Columns: Ozone = mean ozone in parts per billion, 1 pm to 3 pm, Roosevelt Island. Solar.R = solar radiation in Langleys, 8 am to noon, Central Park. Wind = average wind speed in mph at 7 am and 10 am, LaGuardia Airport. Temp = daily maximum temperature in °F, LaGuardia Airport. Source: New York State Department of Conservation (ozone) and National Weather Service (weather), via R's datasets package and the Rdatasets archive.