# 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](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](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](https://bookstack.dtomus.com/uploads/images/gallery/2025-01/scaled-1680-/daily.png)](https://bookstack.dtomus.com/uploads/images/gallery/2025-01/daily.png)

Here is the code that generate it:

```python
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](https://bookstack.dtomus.com/uploads/images/gallery/2025-01/scaled-1680-/avg-month.png)](https://bookstack.dtomus.com/uploads/images/gallery/2025-01/avg-month.png)

Generated by this code:

```python
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](https://bookstack.dtomus.com/uploads/images/gallery/2025-01/scaled-1680-/yearly.png)](https://bookstack.dtomus.com/uploads/images/gallery/2025-01/yearly.png)

Here is the code to plot yearly average temperature:

```python
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](https://bookstack.dtomus.com/uploads/images/gallery/2025-01/7ctlinear-trend.png)](https://bookstack.dtomus.com/uploads/images/gallery/2025-01/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:

```python
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](https://bookstack.dtomus.com/uploads/images/gallery/2025-01/scaled-1680-/sarimax-max.png)](https://bookstack.dtomus.com/uploads/images/gallery/2025-01/sarimax-max.png)

And here we have the predicted minimum temperatures.

[![sarimax_min.png](https://bookstack.dtomus.com/uploads/images/gallery/2025-01/scaled-1680-/sarimax-min.png)](https://bookstack.dtomus.com/uploads/images/gallery/2025-01/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](https://bookstack.dtomus.com/uploads/images/gallery/2025-01/scaled-1680-/sarimax-pred.png)](https://bookstack.dtomus.com/uploads/images/gallery/2025-01/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](https://bookstack.dtomus.com/uploads/images/gallery/2025-01/scaled-1680-/days-over-35.png)](https://bookstack.dtomus.com/uploads/images/gallery/2025-01/days-over-35.png)

And here is the code:

```python
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()

```