# Import necessary modules
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt34 Meteogram
Keywords
weather, meteogram, time series
A weather meteogram is a time-series graphical representation that displays detailed weather information for a specific location over a continuous period. This compact chart captures various meteorological variables such as air and soil temperature, wind speed and direction, precipitation, cloud cover, and atmospheric pressure. Each variable is typically plotted against time on the horizontal axis, allowing for a clear visual analysis of weather trends and patterns.
# Read data and display the first 5 rows
filename = '../datasets/kings_creek_2022_2023_daily.csv'
df = pd.read_csv(filename, parse_dates=['datetime'])
df.head()| datetime | pressure | tmin | tmax | tavg | rmin | rmax | prcp | srad | wspd | wdir | vpd | vwc_5cm | vwc_20cm | vwc_40cm | soiltemp_5cm | soiltemp_20cm | soiltemp_40cm | battv | discharge | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 0 | 2022-01-01 | 96.838 | -14.8 | -4.4 | -9.60 | 78.475 | 98.012 | 0.25 | 2.098 | 5.483 | 0.969 | 0.028 | 0.257 | 0.307 | 0.359 | 2.996 | 5.392 | 7.425 | 8714.833 | 0.0 |
| 1 | 2022-01-02 | 97.995 | -20.4 | -7.2 | -13.80 | 50.543 | 84.936 | 0.25 | 9.756 | 2.216 | 2.023 | 0.072 | 0.256 | 0.307 | 0.358 | 2.562 | 4.250 | 6.692 | 8890.042 | 0.0 |
| 2 | 2022-01-03 | 97.844 | -9.4 | 8.8 | -0.30 | 40.622 | 82.662 | 0.50 | 9.681 | 2.749 | 5.667 | 0.262 | 0.255 | 0.307 | 0.358 | 2.454 | 3.917 | 6.208 | 8924.833 | 0.0 |
| 3 | 2022-01-04 | 96.419 | 0.1 | 8.6 | 4.35 | 48.326 | 69.402 | 0.25 | 8.379 | 5.806 | 2.627 | 0.363 | 0.289 | 0.319 | 0.357 | 2.496 | 3.754 | 5.842 | 8838.292 | 0.0 |
| 4 | 2022-01-05 | 97.462 | -11.1 | -2.2 | -6.65 | 50.341 | 76.828 | 0.00 | 5.717 | 4.207 | 1.251 | 0.126 | 0.313 | 0.337 | 0.357 | 1.688 | 3.429 | 5.567 | 8848.083 | 0.0 |
# Select data for January
start_date = pd.to_datetime('2022-01-01')
end_date = pd.to_datetime('2023-01-01')
idx = (df['datetime'] >= start_date) & (df['datetime'] < end_date)
df = df[idx].copy().reset_index(drop=True)
df.head()| datetime | pressure | tmin | tmax | tavg | rmin | rmax | prcp | srad | wspd | wdir | vpd | vwc_5cm | vwc_20cm | vwc_40cm | soiltemp_5cm | soiltemp_20cm | soiltemp_40cm | battv | discharge | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 0 | 2022-01-01 | 96.838 | -14.8 | -4.4 | -9.60 | 78.475 | 98.012 | 0.25 | 2.098 | 5.483 | 0.969 | 0.028 | 0.257 | 0.307 | 0.359 | 2.996 | 5.392 | 7.425 | 8714.833 | 0.0 |
| 1 | 2022-01-02 | 97.995 | -20.4 | -7.2 | -13.80 | 50.543 | 84.936 | 0.25 | 9.756 | 2.216 | 2.023 | 0.072 | 0.256 | 0.307 | 0.358 | 2.562 | 4.250 | 6.692 | 8890.042 | 0.0 |
| 2 | 2022-01-03 | 97.844 | -9.4 | 8.8 | -0.30 | 40.622 | 82.662 | 0.50 | 9.681 | 2.749 | 5.667 | 0.262 | 0.255 | 0.307 | 0.358 | 2.454 | 3.917 | 6.208 | 8924.833 | 0.0 |
| 3 | 2022-01-04 | 96.419 | 0.1 | 8.6 | 4.35 | 48.326 | 69.402 | 0.25 | 8.379 | 5.806 | 2.627 | 0.363 | 0.289 | 0.319 | 0.357 | 2.496 | 3.754 | 5.842 | 8838.292 | 0.0 |
| 4 | 2022-01-05 | 97.462 | -11.1 | -2.2 | -6.65 | 50.341 | 76.828 | 0.00 | 5.717 | 4.207 | 1.251 | 0.126 | 0.313 | 0.337 | 0.357 | 1.688 | 3.429 | 5.567 | 8848.083 | 0.0 |
# Display number of missing values for each column.
df.isna().sum()datetime 0
pressure 0
tmin 0
tmax 0
tavg 0
rmin 0
rmax 0
prcp 0
srad 0
wspd 1
wdir 28
vpd 2
vwc_5cm 0
vwc_20cm 0
vwc_40cm 0
soiltemp_5cm 0
soiltemp_20cm 0
soiltemp_40cm 0
battv 0
discharge 0
dtype: int64
# Replace missing values
df['wspd'] = df['wspd'].interpolate(method='linear')
df['vpd'] = df['vpd'].interpolate(method='linear')# Display the new number of missing values for each column.
df.isna().sum()datetime 0
pressure 0
tmin 0
tmax 0
tavg 0
rmin 0
rmax 0
prcp 0
srad 0
wspd 0
wdir 28
vpd 0
vwc_5cm 0
vwc_20cm 0
vwc_40cm 0
soiltemp_5cm 0
soiltemp_20cm 0
soiltemp_40cm 0
battv 0
discharge 0
dtype: int64
Estimate some useful metrics
To characterize what happened during the entire year, let’s compute the annual rainfall, maximum wind speed, and maximum and minimum air temperature.
# Find and print total precipitation
P_total = df['prcp'].sum().round(2)
print(f'Total precipitation in 2022 was {P_total} mm')Total precipitation in 2022 was 841.08 mm
# Find the total number of days with measurable precipitation
P_hours = (df['prcp'] > 0).sum()
print(f'There were {P_hours} days with precipitation')There were 94 days with precipitation
# Find median air temperature. Print value.
Tmedian = df['tavg'].median()
print(f'Median air temperature was {Tmedian} Celsius')Median air temperature was 13.65 Celsius
# Find value and time of minimum air temperature. Print value and timestamp.
fmt = '%A, %B %d, %Y'
Tmin_idx = df['tmin'].argmin()
Tmin_value = df.loc[Tmin_idx, 'tmin']
Tmin_timestamp = df.loc[Tmin_idx, 'datetime']
print(f'The lowest air temperature was {Tmin_value} on {Tmin_timestamp:{fmt}}')The lowest air temperature was -22.4 on Thursday, December 22, 2022
# Find value and time of maximum air temperature. Print value and timestamp.
Tmax_idx = df['tmax'].argmax()
Tmax_value = df.loc[Tmax_idx, 'tmax']
Tmax_timestamp = df.loc[Tmax_idx, 'datetime']
print(f'The highest air temperature was {Tmax_value} on {Tmax_timestamp:{fmt}}')The highest air temperature was 37.4 on Saturday, July 23, 2022
# Find max wind gust and time of occurrence. Print value and timestamp.
Wmax_idx = df['wspd'].argmax()
Wmax_value = df.loc[Wmax_idx, 'wspd']
Wmax_timestamp = df.loc[Wmax_idx, 'datetime']
print(f'The highest wind speed was {Wmax_value:.2f} m/s on {Wmax_timestamp:{fmt}}')The highest wind speed was 8.15 m/s on Tuesday, April 12, 2022
Meteogram
# Create meteogram plot
# Define style
plt.style.use('ggplot')
# Define fontsize
font = 14
# Create plot
plt.figure(figsize=(14,30))
# Air temperature
plt.subplot(9,1,1)
plt.title('Kings Creek Meteogram for 2022', size=20)
plt.plot(df['datetime'], df['tmin'], color='navy')
plt.plot(df['datetime'], df['tmax'], color='tomato')
plt.ylabel('Air Temperature (°C)', size=font)
plt.yticks(size=font)
# Relative humidity
plt.subplot(9,1,2)
plt.plot(df['datetime'], df['rmin'], color='navy')
plt.plot(df['datetime'], df['rmax'], color='tomato')
plt.ylabel('Relative Humidity (%)', size=font)
plt.yticks(size=font)
plt.ylim(0,110)
# Atmospheric pressure
plt.subplot(9,1,3)
plt.plot(df['datetime'], df['pressure'], '-k')
plt.ylabel('Pressure (kPa)', size=font)
plt.yticks(size=font)
# Vapor pressure deficit
plt.subplot(9,1,4)
plt.plot(df['datetime'], df['vpd'], '-k')
plt.ylabel('Vapor pressure deficit (kPa)', size=font)
plt.yticks(size=font)
# Wind speed
plt.subplot(9,1,5)
plt.plot(df['datetime'], df['wspd'], '-k', label='Wind speed')
plt.ylabel(r'Wind Speed ($m \ s^{-1}$)', size=font)
plt.legend(loc='upper left')
plt.yticks(size=font)
# Solar radiation
plt.subplot(9,1,6)
plt.plot(df['datetime'], df['srad'])
plt.ylabel(r'Solar radiation ($W \ m^{-2}$)', size=font)
plt.yticks(size=font)
# Precipitation
plt.subplot(9,1,7)
plt.step(df['datetime'], df['prcp'], color='navy')
plt.ylabel('Precipitation (mm)', size=font)
plt.yticks(size=font)
plt.ylim(0.01,35)
plt.text(df['datetime'].iloc[5], 30, f"Total = {P_total} mm", size=14)
# Soil temperature
plt.subplot(9,1,8)
plt.plot(df['datetime'], df['soiltemp_5cm'], '-k', label='5 cm')
plt.plot(df['datetime'], df['soiltemp_20cm'], '-g', label='20 cm')
plt.plot(df['datetime'], df['soiltemp_40cm'], '--r', label='40 cm')
plt.ylabel('Soil temperature (°C)', size=font)
plt.yticks(size=font)
plt.ylim(df['soiltemp_5cm'].min()-10, df['soiltemp_5cm'].max()+10)
plt.grid(which='minor')
plt.legend(loc='upper left')
# Soil moisture
plt.subplot(9,1,9)
plt.plot(df['datetime'], df['vwc_5cm'], '-k', label='5 cm')
plt.plot(df['datetime'], df['vwc_20cm'], '-g', label='20 cm')
plt.plot(df['datetime'], df['vwc_40cm'], '--r', label='40 cm')
plt.ylabel(r'Soil Moisture ($m^3 \ m^{-3}$)', size=font)
plt.yticks(size=font)
plt.ylim(0, 0.5)
plt.grid(which='minor')
plt.legend(loc='best')
plt.subplots_adjust(hspace=0.2) # for space between columns wspace=0)
#plt.savefig('meteogram.svg', format='svg')
plt.show()