Visualizing the Temperature in Cambridge, UK

(6 comments)

The Digital Technology Group (DTG) at Cambridge University has been recording the weather from the roof of their building since 1995. The complete data are available to download in CSV format from the DTG website as the file weather-raw.csv.

The script below visualizes these data as a polar scatter plot with the day of the year indicated by the angle:

enter image description here

The year can be extended as the vertical axis of a 3D plot, as in the following example:

enter image description here

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from matplotlib import cm
from matplotlib.colors import Normalize
from mpl_toolkits.mplot3d import Axes3D
plt.rcParams['text.usetex'] = True

# Read the data into a DataFrame, using the timestamp as the index and selecting
# the temperature column.
df = pd.read_csv('weather-raw.csv', names=['timestamp', 'T'], usecols=(0,1),
                 index_col=[0])
df.index = pd.to_datetime(df.index)

# The temperature in the data file is encoded as 10 * T, so retrieve the real
# temperature, in degC.
df['T'] /= 10

# Select the maximum temperature on each day of the year.
df2 = df.groupby(pd.Grouper(level='timestamp', freq='D')).max()

# Convert the timestamp to the number of seconds since the start of the year.
df2['secs'] = (df2.index - pd.to_datetime(df2.index.year, format='%Y')).total_seconds()
# Approximate the angle as the number of seconds for the timestamp divide by
# the number of seconds in an average year.
df2['angle'] = df2['secs'] / (365.25 * 24 * 60 * 60) * 2 * np.pi

# For the colourmap, the minimum is the largest multiple of 5 not greater than
# the smallest value of T; the maximum is the smallest multiple of 5 not less
# than the largest value of T, e.g. (-3.2, 40.2) -> (-5, 45).
Tmin = 5 * np.floor(df2['T'].min() / 5)
Tmax = 5 * np.ceil(df2['T'].max() / 5)

# Normalization of the colourmap.
norm = Normalize(vmin=Tmin, vmax=Tmax)
c = norm(df2['T'])

def plot_polar():
    fig = plt.figure()
    ax = fig.add_subplot(projection='polar')
    # We prefer 1 January (0 deg) on the left, but the default is to the
    # right, so offset by 180 deg.
    ax.set_theta_offset(np.pi)
    cmap = cm.turbo
    ax.scatter(df2['angle'], df2['T'], c=cmap(c), s=2)

    # Tick labels.
    ax.set_xticks(np.arange(0, 2 * np.pi, np.pi / 6))
    ax.set_xticklabels(['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun',
                        'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'])
    ax.set_yticks([])

    # Add and title the colourbar.
    cbar = fig.colorbar(cm.ScalarMappable(norm=norm, cmap=cmap),
                        ax=ax, orientation='vertical', pad=0.1)
    cbar.ax.set_title(r'$T\;/^\circ\mathrm{C}$')

    plt.show()

def plot_3d():
    fig = plt.figure()
    ax = fig.add_subplot(projection='3d')
    cmap = cm.turbo
    X = df2['T'] * np.cos(df2['angle'] + np.pi)
    Y = df2['T'] * np.sin(df2['angle'] + np.pi)
    z = df2.index.year
    ax.scatter(X, Y, z, c=cmap(c), s=2)

    ax.set_xticks([])
    ax.set_yticks([])
    cbar = fig.colorbar(cm.ScalarMappable(norm=norm, cmap=cmap),
                        ax=ax, orientation='horizontal', pad=-0.02, shrink=0.6)
    cbar.ax.set_title(r'$T\;/^\circ\mathrm{C}$')
    plt.show()

plot_polar()
plot_3d()
Current rating: 5

Comments

Comments are pre-moderated. Please be patient and your comment will appear soon.

Kemal 4 months, 1 week ago

I am constantly learning something new from your posts Christian.. Appreciated!

Link | Reply
Currently unrated

Kane 3 months, 4 weeks ago

I put weather-raw.csv in my personal directory and got this error:
FileNotFoundError: [WinError 2] The system cannot find the file specified

I tried this and it gave the same error:

import os

here = os.path.dirname(os.path.abspath(__file__))
print('here: ',here)

filename = os.path.join(here, 'weather-raw.csv')
print('filename: ',filename)

df = pd.read_csv(filename, names=['timestamp', 'T'], usecols=(0,1), index_col=[0])

Link | Reply
Currently unrated

christian 3 months, 4 weeks ago

I'm not sure what you mean by your personal directory, but with the approach in your code, the file weather-raw.csv should be in the same directory as the script you are running.

If your data file is in your home directory, then you want something like:

from pathlib import Path

home = str(Path.home())

filename = os.path.join(home, 'weather-raw.csv')

Link | Reply
Currently unrated

Doug Brown 3 months, 3 weeks ago

I'm using a jupyter note book for my IDE
and get this error
RuntimeError: Failed to process string with tex because latex could not be found

I've only used LaTex as a "publication' editor, and don't know how it finds its way into python

Link | Reply
Currently unrated

christian 3 months, 3 weeks ago

I think this is the same problem you encountered before, isn't it?
If you're on Windows, this might help: https://stackoverflow.com/questions/58121461/runtimeerror-failed-to-process-string-with-tex-because-latex-could-not-be-found  – you apparently need to ensure that the Latex executable and additional applications are on your system PATH.

Link | Reply
Currently unrated

Doug Brown 3 months, 3 weeks ago

Thank you
I was using LayTex through a web version.
I slogged thru an install and all is fine.
Thanks.

Link | Reply
Currently unrated

New Comment

required

required (not published)

optional

required