Temperatures in Melbourne - historical data

Use this links to download the data:

For max temp: http://www.bom.gov.au/climate/change/hqsites/data/temp/tmax.086338.daily.csv

For min temp: http://www.bom.gov.au/climate/change/hqsites/data/temp/tmin.086338.daily.csv

Plot daily temperatures

Here is the attempt to plot the daily max and min temperature. The plot looks very crowded:daily.png

Here is the code that generate it:

import pandas as pd
import matplotlib.pyplot as plt
import matplotlib.dates as mdates

df_max = pd.read_csv('tmax.csv')
df_min = pd.read_csv('tmin.csv')

df_max['Date'] = pd.to_datetime(df_max['Date'], dayfirst=True).dt.to_period('D')
df_min['Date'] = pd.to_datetime(df_min['Date'], dayfirst=True).dt.to_period('D')

# Reset the index
df_max = df_max.reset_index()
df_min = df_min.reset_index()

# Convert Period to datetime
df_max['Date'] = df_max['Date'].dt.to_timestamp()
df_min['Date'] = df_min['Date'].dt.to_timestamp()

# Plotting
plt.figure(figsize=(16,6))
plt.plot(df_max['Date'], df_max['t_max'], color='red', label='MaxTemp')
plt.plot(df_min['Date'], df_min['t_min'], color='blue', label='MinTemp')
plt.legend()
plt.xlabel('Date')
plt.ylabel('Temperature')
plt.gca().xaxis.set_major_formatter(mdates.DateFormatter('%Y-%m'))  # Format dates as 'YYYY-MM'
plt.gcf().autofmt_xdate()  # Slant dates for better readability
plt.show()


Plot monthly temperature

To clean the plot we compute monthly average:avg_month.png

Generated by this code:

import matplotlib.pyplot as plt
import pandas as pd

df_max = pd.read_csv('tmax.csv')
df_min = pd.read_csv('tmin.csv')

# Assuming df_max and df_min are your DataFrames
df_max = df_max.reset_index()
df_min = df_min.reset_index()

# Convert 'Date' column to datetime
df_max['Date'] = pd.to_datetime(df_max['Date'], dayfirst=True)
df_min['Date'] = pd.to_datetime(df_min['Date'], dayfirst=True)

# Calculate average temperature of every month
df_max_month_avg = df_max.groupby(df_max['Date'].dt.to_period('M'))['t_max'].mean().reset_index()
df_min_month_avg = df_min.groupby(df_min['Date'].dt.to_period('M'))['t_min'].mean().reset_index()

# Rename columns
df_max_month_avg.columns = ['Month', 'Average Max Temperature']
df_min_month_avg.columns = ['Month', 'Average Min Temperature']

#Convert the 'Month' column to datetime objects:
df_max_month_avg['Month'] = df_max_month_avg['Month'].dt.to_timestamp()
df_min_month_avg['Month'] = df_min_month_avg['Month'].dt.to_timestamp()


# Plotting
plt.figure(figsize=(16,6))
plt.plot(df_max_month_avg['Month'], df_max_month_avg['Average Max Temperature'], color='red', label='MaxTemp')
plt.plot(df_min_month_avg['Month'], df_min_month_avg['Average Min Temperature'], color='blue', label='MinTemp')
plt.legend()
plt.xlabel('Month')
plt.ylabel('Temperature')
plt.title('Average Temperature of every month')
plt.xticks(rotation=45)
plt.show()

 

Plot yearly average temperature

Here is the result, much cleaner and shows a small trend in temperature increase over 100 years by 2 degrees.

yearly.png

Here is the code to plot yearly average temperature:

import matplotlib.pyplot as plt
import pandas as pd

df_max = pd.read_csv('tmax.csv')
df_min = pd.read_csv('tmin.csv')

# Assuming df_max and df_min are your DataFrames
df_max = df_max.reset_index()
df_min = df_min.reset_index()

# Convert 'Date' column to datetime
df_max['Date'] = pd.to_datetime(df_max['Date'], dayfirst=True)
df_min['Date'] = pd.to_datetime(df_min['Date'], dayfirst=True)

# Calculate average temperature every year
df_max_year_avg = df_max.groupby(df_max['Date'].dt.year)['t_max'].mean().reset_index()
df_min_year_avg = df_min.groupby(df_min['Date'].dt.year)['t_min'].mean().reset_index()

# Rename columns
df_max_year_avg.columns = ['Year', 'Average Max Temperature']
df_min_year_avg.columns = ['Year', 'Average Min Temperature']

# Plotting
plt.figure(figsize=(16,6))
plt.plot(df_max_year_avg['Year'], df_max_year_avg['Average Max Temperature'], color='red', label='MaxTemp')
plt.plot(df_min_year_avg['Year'], df_min_year_avg['Average Min Temperature'], color='blue', label='MinTemp')
plt.legend()
plt.xlabel('Year')
plt.ylabel('Temperature, C')
plt.title('Average Temperature every year')
plt.xticks(rotation=45)
plt.show()

Predict the temperature rise for the next 500 years

Using a linear interpolation here is the trend in temperature increase. 

linear trend.png

Interesting to see that the max temperatures will increase from around 20C to 23 in 500 years whereas the minimum temperatures have a steeper trend going from 11C to 19C for the same period of time. There will be hotter nights but days will remain almost the same.

Here is the code:

import matplotlib.pyplot as plt
import pandas as pd
import numpy as np

df_max = pd.read_csv('tmax.csv')
df_min = pd.read_csv('tmin.csv')

# Assuming df_max and df_min are your DataFrames
df_max = df_max.reset_index()
df_min = df_min.reset_index()

# Convert 'Date' column to datetime
df_max['Date'] = pd.to_datetime(df_max['Date'], dayfirst=True)
df_min['Date'] = pd.to_datetime(df_min['Date'], dayfirst=True)

# Calculate average temperature every year
df_max_year_avg = df_max.groupby(df_max['Date'].dt.year)['t_max'].mean().reset_index()
df_min_year_avg = df_min.groupby(df_min['Date'].dt.year)['t_min'].mean().reset_index()

# Rename columns
df_max_year_avg.columns = ['Year', 'Average Max Temperature']
df_min_year_avg.columns = ['Year', 'Average Min Temperature']

# Calculate slope and intercept of temperature trend
slope_max = (df_max_year_avg['Average Max Temperature'].iloc[-1] - df_max_year_avg['Average Max Temperature'].iloc[0]) / (df_max_year_avg['Year'].iloc[-1] - df_max_year_avg['Year'].iloc[0])
intercept_max = df_max_year_avg['Average Max Temperature'].iloc[0] - slope_max * df_max_year_avg['Year'].iloc[0]

slope_min = (df_min_year_avg['Average Min Temperature'].iloc[-1] - df_min_year_avg['Average Min Temperature'].iloc[0]) / (df_min_year_avg['Year'].iloc[-1] - df_min_year_avg['Year'].iloc[0])
intercept_min = df_min_year_avg['Average Min Temperature'].iloc[0] - slope_min * df_min_year_avg['Year'].iloc[0]

# Extrapolate temperature trend for next 500 years
years_future = np.arange(df_max_year_avg['Year'].iloc[-1] + 1, df_max_year_avg['Year'].iloc[-1] + 501)
temp_max_future = slope_max * years_future + intercept_max
temp_min_future = slope_min * years_future + intercept_min

# Plotting
plt.figure(figsize=(16,6))
plt.plot(df_max_year_avg['Year'], df_max_year_avg['Average Max Temperature'], color='red', label='MaxTemp')
plt.plot(df_min_year_avg['Year'], df_min_year_avg['Average Min Temperature'], color='blue', label='MinTemp')
plt.plot(years_future, temp_max_future, color='red', linestyle='--', label='MaxTemp Future')
plt.plot(years_future, temp_min_future, color='blue', linestyle='--', label='MinTemp Future')
plt.legend()
plt.xlabel('Year')
plt.ylabel('Temperature, C')
plt.grid(axis='y', linestyle='--', linewidth=0.5)
plt.title('Average Temperature every year')
plt.xticks(rotation=45)
plt.show()

 

Prediction using SARIMAX

It is interesting to come across this SARIMAX prediction model suggested by Ollama model qwen2.5:13b.

Here is the prediction for the existing maximum temperatures.

sarimax_max.png  

And here we have the predicted minimum temperatures.

sarimax_min.png

It seems pretty accurate.

And the prediction for the next 240 years. The model can't take date beyond 2240.

sarimax_pred.png 

Days over 35 °C

Interesting to see how many days are over 35 C. It seems that between 1995 and 2020 we got more days over 35C than before.

days_over_35.png

And here is the code:

import matplotlib.pyplot as plt
import pandas as pd
import matplotlib.ticker as ticker

df_max = pd.read_csv('tmax.csv')
#df_min = pd.read_csv('tmin.csv')

# Assuming df is your DataFrame
df = df_max.reset_index()

# Convert 'Date' column to datetime
df['Date'] = pd.to_datetime(df['Date'], dayfirst=True)

# Calculate number of days over 35°C temperature every year
df_over_35 = df[df['t_max'] > 35]
df_over_35_year = df_over_35.groupby(df_over_35['Date'].dt.year)['t_max'].count().reset_index()

# Rename columns
df_over_35_year.columns = ['Year', 'Number of Days Over 35°C']

# Calculate average
average = df_over_35_year['Number of Days Over 35°C'].mean()

# Plotting
plt.figure(figsize=(16,6))
plt.plot(df_over_35_year['Year'], df_over_35_year['Number of Days Over 35°C'], color='red')
plt.xlabel('Year')
plt.ylabel('Number of Days Over 35°C')
plt.title('Number of Days Over 35°C every year')
plt.axhline(y=average, color='green', linestyle='--', label='Average')
plt.legend()
plt.gca().yaxis.set_major_locator(ticker.MultipleLocator(1))
#plt.grid(axis='y', linestyle='--', linewidth=0.5)
plt.xticks(range(df_over_35_year['Year'].min(), df_over_35_year['Year'].max()+1, 5))
plt.grid(axis='x', linestyle='--', linewidth=0.5)
plt.xticks(rotation=45)
plt.show()