4. Matplotlib plot json

Matplotlib can be used to draw a graph of json data from the web.

4.1. Temperature forecast

../_images/Melb_Temp_forecast_Jul_2023.png

4.2. Python code

The python code is below.
The code is commented to indicate what each part is doing.
 1
 2import numpy as np
 3import matplotlib.pyplot as plt
 4import json
 5from urllib.request import urlopen
 6from datetime import datetime, timedelta
 7from pathlib import Path
 8
 9
10def plot_weather_temperatures(title, url):
11    """Plots the weather data from the given url and gives it the given title.
12
13    Args:
14        title (str): The title of the plot.
15        url (str): The url of the API that provides weather data.
16
17    Returns:
18        None
19    """
20    # Open the URL and read its content
21    with urlopen(url) as response:
22        source = response.read()
23    # Load the content as a JSON object
24    data = json.loads(source)
25    # Extract the list of dates from the "daily" key of the JSON object
26    dates_list = data["daily"]["time"]
27    # Extract the list of maximum temperatures from the "daily" key of the JSON object
28    tmax = data["daily"]["temperature_2m_max"]
29    # Extract the list of minimum temperatures from the "daily" key of the JSON object
30    tmin = data["daily"]["temperature_2m_min"]
31    # Convert the dates in dates_list to datetime objects
32    dates_list = [datetime.strptime(date, "%Y-%m-%d") for date in dates_list]
33    # plot lines with x, y, colour, markers, labels for legend
34    plt.plot(dates_list, tmax, color='darkred', marker='o', label = "Max Temp")
35    plt.plot(dates_list, tmin, color='blue', marker='x', label = "Min Temp")
36    # Set the offset values for the x and y coordinates of the temperature labels
37    x_offset = timedelta(days=0.2)
38    max_offset = 0.7
39    min_offset = -1.2
40    # Label the maximum temperatures
41    for x, y in zip(dates_list, tmax):
42        plt.text(x - x_offset, y + max_offset, f"{y:.1f}", color="darkred", fontsize=8)
43    # Label the minimum temperatures
44    for x, y in zip(dates_list, tmin):
45        plt.text(x - x_offset, y + min_offset, f"{y:.1f}", color="blue", fontsize=8)
46    # Set the bottom limit of the y-axis to the minimum of 0 and 2 units below the minimum temperature,
47    # and set the top limit of the y-axis to 2 units above the maximum temperature
48    plt.ylim(bottom=min(0, min(tmin) - 2), top=max(tmax) + 2)
49    # Set the y ticks to be every 2 units
50    ymin = min(0, min(tmin) - 2)
51    ymax = max(tmax) + 2
52    plt.yticks(np.arange(ymin, ymax, 2))
53    # format dates so they are angled to fit
54    plt.gcf().autofmt_xdate()
55    # Set the font size of the x-axis labels to 10 points
56    plt.tick_params(axis='x', labelsize=8)
57    # add a grid
58    plt.grid(True)
59    # add axis title labels
60    plt.xlabel('Date', fontsize=14)
61    # \N{DEGREE SIGN} si the escape sequence for unicode name for the degree symbol
62    plt.ylabel('Temperature (\N{DEGREE SIGN}C)', fontsize=14)
63    # add plot title
64    plt.title(title,fontsize=18)
65    # place legend at lower right
66    plt.legend(loc="lower right")
67    # Get the directory of the current file
68    currfile_dir = Path(__file__).parent
69    # Replace spaces in title with underscores to create filename for saving figure
70    filename = title.replace(" ", "_")
71    # build the image file path
72    filepath = currfile_dir / (f"{filename}.png")
73    # Save figure (dpi 300 is good when saving so graph has high resolution)
74    plt.savefig(filepath, dpi=600)
75    # Show plot
76    plt.show()
77
78
79def plot_melb_temp_7day():
80    url = "https://api.open-meteo.com/v1/forecast?latitude=-37.81&longitude=144.96&daily=temperature_2m_max,temperature_2m_min&timezone=Australia%2FSydney"
81    title = "Melb Temp forecast Jul 2023"
82    plot_weather_temperatures(title, url)
83
84
85if __name__ == '__main__':
86    plot_melb_temp_7day()