Climate Change Data Visualization in Python

Constructed interactive maps using GeoJson, Matplotlib, Plotly, and Seaborn to identify and analyze patterns in the time-series climate change data…
Python
Numpy
Matplotlib
Ploly
Geojson
Author

Rebekah Chuang

Published

January 15, 2023

# run this if env already exists
library(reticulate)
use_virtualenv("my_python_env")
Code
import pandas as pd
import numpy as np
import matplotlib.pyplot as mlp
import plotly.express as px
import plotly.graph_objects as go
from plotly.subplots import make_subplots
from urllib.request import urlopen
import json
Code
 # Create dataframes using pandas. Merged and dropped irrelevant columns after viewing the csv in Excel and we have to use "latin-1" encoding for ANSI for the model_county
national_data = pd.read_csv('https://raw.githubusercontent.com/washingtonpost/data-2C-beyond-the-limit-usa/main/data/processed/climdiv_national_year.csv', dtype={"fips": str})
state_data = pd.merge(pd.read_csv('https://raw.githubusercontent.com/washingtonpost/data-2C-beyond-the-limit-usa/main/data/processed/climdiv_state_year.csv', dtype={"fips": str}), pd.read_csv('https://raw.githubusercontent.com/washingtonpost/data-2C-beyond-the-limit-usa/main/data/processed/model_state.csv', dtype={"fips": str}), on ='fips')
county_data = pd.merge(pd.read_csv('https://raw.githubusercontent.com/washingtonpost/data-2C-beyond-the-limit-usa/main/data/processed/climdiv_county_year.csv', dtype={"fips": str}), pd.read_csv('https://raw.githubusercontent.com/washingtonpost/data-2C-beyond-the-limit-usa/main/data/processed/model_county.csv', encoding = "latin-1", dtype={"fips": str}), on ='fips')

Temperatures by State per Year

Code
with urlopen('https://raw.githubusercontent.com/PublicaMundi/MappingAPI/master/data/geojson/us-states.json') as response:
    states = json.load(response)

fig = px.choropleth_mapbox(state_data,
                    geojson=states,
                    locations='fips',
                    color='temp',
                    color_continuous_scale = 'sunset',
                    range_color=(35, 75),
                    labels = {'temp':'Temperature'},
                    hover_name = 'STATE_NAME',
                    hover_data = ["Annual"],
                    mapbox_style = 'open-street-map',
                    zoom= 3,
                    center = {'lat' : 37.0902, 'lon' : -95.7129},
                    opacity = 0.8,
                    animation_frame='year')

fig.update_layout(
    margin={"r":0,"t":0,"l":0,"b":0},
    geo_scope='usa',
    )
fig.show()

Comparison between max & min temp(by state)

Code
max_min_groupby_state = state_data.groupby(['fips', 'STATE_NAME'])['temp'].agg([min, max]).reset_index()
max_min_groupby_state = max_min_groupby_state.sort_values('max', ascending = False)
/var/folders/p_/1gsw3d7d0q91kz_4jb8s9v4r0000gn/T/ipykernel_2970/3699623925.py:1: FutureWarning:

The provided callable <built-in function min> is currently using SeriesGroupBy.min. In a future version of pandas, the provided callable will be used directly. To keep current behavior pass the string "min" instead.

/var/folders/p_/1gsw3d7d0q91kz_4jb8s9v4r0000gn/T/ipykernel_2970/3699623925.py:1: FutureWarning:

The provided callable <built-in function max> is currently using SeriesGroupBy.max. In a future version of pandas, the provided callable will be used directly. To keep current behavior pass the string "max" instead.
Code
fig = make_subplots(specs=[[{'secondary_y': True}]])

fig.add_trace(
    go.Scatter(x = max_min_groupby_state['STATE_NAME'],
               y = max_min_groupby_state['max'],
               name = 'maximum temp'),
               secondary_y = False)

fig.add_trace(
    go.Scatter(x = max_min_groupby_state['STATE_NAME'],
               y = max_min_groupby_state['min'],
               name="minimum temp"),
               secondary_y = True)

fig.update_layout(
            title={
                'text' : 'Temperature Difference by State',
                'x' : 0.5,
                'xanchor' : 'center'})

# Set x-axis title
fig.update_xaxes(title_text = 'State')

# Set y-axes titles(using same scale)
fig.update_yaxes(title_text = 'Temperature in Fahrenheit',
                 range=[30,75],
                 secondary_y = False)

fig.update_yaxes(range=[30,75], secondary_y=True)

fig.update_traces(mode='lines')

fig.update_layout(hovermode = 'x unified')
fig.show()

Temperatures by County for 2019

Code
with urlopen('https://raw.githubusercontent.com/plotly/datasets/master/geojson-counties-fips.json') as response:
    counties = json.load(response)

fig = px.choropleth(county_data[county_data['year']==2019], 
                    geojson=counties, 
                    locations='fips', 
                    color='temp',
                    color_continuous_scale="sunset",
                    range_color=(35, 75),
                    hover_name="CTYNAME",
                    hover_data=["STNAME", "Annual"],
                    scope="usa",
                    labels={'temp':'temperature'})

fig.update_layout(margin={"r":0,"t":0,"l":0,"b":0})
fig.show()

Temperature in Illinois by County for 2019

Code
county_data_illinois = county_data[county_data['STNAME'] == 'Illinois']
county_data_illinois_2019 = county_data_illinois[county_data_illinois['year']==2019]
Code
with urlopen('https://raw.githubusercontent.com/plotly/datasets/master/geojson-counties-fips.json') as response:
    counties = json.load(response)

fig = px.choropleth_mapbox(county_data_illinois_2019,
                    geojson = counties,
                    locations = 'fips',
                    color = 'temp',
                    color_continuous_scale = "sunset",
                    range_color = (45, 60),
                    labels = {'temp':'Temperature'},
                    hover_name = 'CTYNAME',
                    mapbox_style = 'open-street-map',
                    zoom = 5,
                    center = {"lat": 40.1164, "lon": -88.2434},
                    opacity=0.8)

fig.update_layout(margin={"r":0,"t":0,"l":0,"b":0})
fig.show()

Average Temperature Comparison(National&Illinois)

Code
state_data_illinois = state_data[state_data['STATE_NAME'] == 'Illinois']
Code
#Merge 2 tables: national_data & state_data_illinois
national_illinois = pd.merge(national_data,
                             state_data_illinois,
                             on = 'year',
                             suffixes= ['_n','_i'])

fig = make_subplots(specs=[[{"secondary_y": True}]])

fig.add_trace(
    go.Scatter(x = national_illinois['year'],
               y=national_illinois['temp_n'],
               name="national_temp"),
               secondary_y=False)

fig.add_trace(
    go.Scatter(x = national_illinois['year'],
               y = national_illinois['temp_i'],
               name="illinois_temp"),
               secondary_y=True)

fig.update_layout(
            title={
                'text' : 'National/Illinois Temperature Change 1895-2019',
                'x':0.5,
                'xanchor': 'center'
            })

# Set x-axis title
fig.update_xaxes(title_text='year')

# Set y-axis title (using same scale)
fig.update_yaxes(title_text='Temperature in Fahrenheit',
                 range=[48,56],
                 secondary_y=False)
fig.update_yaxes(range=[48,56],
                 secondary_y = True)

fig.update_traces(mode='lines',
                  hovertemplate=None)
fig.update_layout(hovermode="x unified")

fig.show()