Search code examples
pythonmatplotlibvisualization

What is the simplest way to make a Hovmöller diagram or heatmap with dates with Matplotlib?


I've tried checking out a lot of similar questions and their answers, but I still struggle to find a good solution. In most cases it seems to be geared towards heatmaps where both axes is some kind of number rather than a date as in my case. Hovmöller diagrams seem to be more or less what I'm looking for, but I've struggled to find information about what the easiest way to generate them would be, as they seem to essentially just be a kind of heatmap with binned times as well. When I've tried to use solutions like hist2d the errors I get seem to be related to the fact that one axis consists of datetimes, even if I cast them to numpy.datetime64 first as one answer suggested.

Essentially what I have is a list of dates and a corresponding list of longitudes as data points (dates can occur multiple times in this list, in which case there will be multiple longitudes on that date), and I'd essentially want to at the very least bin the longitudes into single degrees (i.e. all longitudes between 0° and 1° in one bin, and so on), and presumably I'd also make bins consisting of multiple times too (since slivers of single dates would be far too thin to represent properly, as there are ~5.5k dates total, and it would of course be best with a solution that can be extended to more dates too).

I've considered writing some code to bin them manually and see if that works, but if anyone knows of any simple solutions geared towards exactly what I'm talking about, I'd love to hear it.


Solution

  • hist2d does not yet directly support datetimes but you can pass in floats derived from your dates and then directly tell Matplotlib to format them as dates:

    import datetime
    
    import numpy as np
    import matplotlib.pyplot as plt
    import matplotlib.dates as mdates
    
    # Create some random dates and longitudes
    rng = np.random.default_rng(seed=42)
    dates = [datetime.date(2024, 4, d) for d in rng.integers(low=1, high=31, size=100)]
    longitudes = rng.integers(low=20, high=31, size=100)
    
    fig, ax = plt.subplots()
    
    # Plot histogram with dates converted to floats
    ax.hist2d(mdates.date2num(dates), longitudes)
    
    # Fortmat x-axis as dates
    ax.xaxis.set_major_locator(mdates.AutoDateLocator())
    ax.xaxis.set_major_formatter(mdates.AutoDateFormatter(ax.xaxis.get_major_locator()))
    fig.autofmt_xdate()
    
    plt.show()
    

    enter image description here