Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to pass date array to pcolor plot?

I have matrix-data where one axis relates to dates. However, I'm having problems passing this data on as an axis to pcolor. My dummy data is as follows:

In [219]: X = [datetime.date.today() + datetime.timedelta(days=i) for i in range(4)]

In [220]: Y = arange(5)

In [221]: Z = arange(4*5).reshape(4, 5)

The naive attemp pcolor(Y, X, Z) fails because pcolor does not like to get a list object:

In [222]: pcolor(Y, X, Z)
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
<ipython-input-222-1ece18b4bc13> in <module>()
----> 1 pcolor(Y, X, Z)

/export/data/home/gholl/venv/gerrit/lib/python3.4/site-packages/matplotlib/pyplot.py in pcolor(*args, **kwargs)
   2926         ax.hold(hold)
   2927     try:
-> 2928         ret = ax.pcolor(*args, **kwargs)
   2929         draw_if_interactive()
   2930     finally:

/export/data/home/gholl/venv/gerrit/lib/python3.4/site-packages/matplotlib/axes.py in pcolor(self, *args, **kwargs)
   7545         shading = kwargs.pop('shading', 'flat')
   7546 
-> 7547         X, Y, C = self._pcolorargs('pcolor', *args, allmatch=False)
   7548         Ny, Nx = X.shape
   7549 

/export/data/home/gholl/venv/gerrit/lib/python3.4/site-packages/matplotlib/axes.py in _pcolorargs(funcname, *args, **kw)
   7357 
   7358         Nx = X.shape[-1]
-> 7359         Ny = Y.shape[0]
   7360         if len(X.shape) != 2 or X.shape[0] == 1:
   7361             x = X.reshape(1, Nx)

AttributeError: 'list' object has no attribute 'shape'

Converting it to an array containing datetime.date fails with TypeError: float() argument must be a string or a number, not 'datetime.date':

In [223]: pcolor(Y, numpy.array(X), Z)                                                                                                                                 
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-223-a00423a6d479> in <module>()
----> 1 pcolor(Y, numpy.array(X), Z)

/export/data/home/gholl/venv/gerrit/lib/python3.4/site-packages/matplotlib/pyplot.py in pcolor(*args, **kwargs)
   2926         ax.hold(hold)
   2927     try:
-> 2928         ret = ax.pcolor(*args, **kwargs)
   2929         draw_if_interactive()
   2930     finally:

/export/data/home/gholl/venv/gerrit/lib/python3.4/site-packages/matplotlib/axes.py in pcolor(self, *args, **kwargs)
   7606             kwargs['antialiaseds'] = False
   7607 
-> 7608         collection = mcoll.PolyCollection(verts, **kwargs)
   7609 
   7610         collection.set_alpha(alpha)

/export/data/home/gholl/venv/gerrit/lib/python3.4/site-packages/matplotlib/collections.py in __init__(self, verts, sizes, closed, **kwargs)
    743         Collection.__init__(self, **kwargs)
    744         self._sizes = sizes
--> 745         self.set_verts(verts, closed)
    746 
    747     def set_verts(self, verts, closed=True):

/export/data/home/gholl/venv/gerrit/lib/python3.4/site-packages/matplotlib/collections.py in set_verts(self, verts, closed)
    763                     codes[0] = mpath.Path.MOVETO
    764                     codes[-1] = mpath.Path.CLOSEPOLY
--> 765                     self._paths.append(mpath.Path(xy, codes))
    766                 else:
    767                     self._paths.append(mpath.Path(xy))

/export/data/home/gholl/venv/gerrit/lib/python3.4/site-packages/matplotlib/path.py in __init__(self, vertices, codes, _interpolation_steps, closed, readonly)
    131             vertices = vertices.astype(np.float_).filled(np.nan)
    132         else:
--> 133             vertices = np.asarray(vertices, np.float_)
    134 
    135         if codes is not None:

/export/data/home/gholl/venv/gerrit/lib/python3.4/site-packages/numpy/core/numeric.py in asarray(a, dtype, order)
    460 
    461     """
--> 462     return array(a, dtype, copy=False, order=order)
    463 
    464 def asanyarray(a, dtype=None, order=None):

TypeError: float() argument must be a string or a number, not 'datetime.date'

Finally, converting it to a proper numpy.datetime64 object does not resolve the situation either, failing with Invalid type promotion:

In [224]: pcolor(Y, numpy.array(X, dtype="datetime64[D]"), Z)
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-224-0ac06cfafa35> in <module>()
----> 1 pcolor(Y, numpy.array(X, dtype="datetime64[D]"), Z)

/export/data/home/gholl/venv/gerrit/lib/python3.4/site-packages/matplotlib/pyplot.py in pcolor(*args, **kwargs)
   2926         ax.hold(hold)
   2927     try:
-> 2928         ret = ax.pcolor(*args, **kwargs)
   2929         draw_if_interactive()
   2930     finally:

/export/data/home/gholl/venv/gerrit/lib/python3.4/site-packages/matplotlib/axes.py in pcolor(self, *args, **kwargs)
   7577                              X4[:, newaxis], Y4[:, newaxis],
   7578                              X1[:, newaxis], Y1[:, newaxis]),
-> 7579                              axis=1)
   7580         verts = xy.reshape((npoly, 5, 2))
   7581 

TypeError: invalid type promotion

What would be the correct way to proceed here? In the

Note that the answer to the question plotting date data with pcolor uses scatter, not pcolor, and therefore does not help in my situation.

like image 322
gerrit Avatar asked Mar 18 '23 09:03

gerrit


1 Answers

Matplotlib uses simple floats to represent datetimes. Hence you have to convert them first and then tell the axis that is has to format the labels as dates. Matplotlib provides the function date2num for that:

import matplotlib.pyplot as plt
import matplotlib.dates as mdates
import datetime
import numpy as np

# Your original data (with adapted sizes)
x = [datetime.date.today() + datetime.timedelta(days=i) for i in range(4)]
y = np.arange(5)
z = np.arange(3*4).reshape(3, 4).T

# Convert to numbers
x = mdates.date2num(x)

# Create the figure
fig, ax = plt.subplots(1,1)
plt.pcolor(x,y,z)

# Setup the DateFormatter for the x axis
date_format = mdates.DateFormatter('%D')
ax.xaxis.set_major_formatter(date_format)

# Rotates the labels to fit
fig.autofmt_xdate()

plt.show()

Some other remarks:

  • For pcolor the x and y vectors represent the corner points of the tiles. So they need to be 1 element longer than the data.
  • The documentation provides a nice overview of how to handle dates in matplotlib.

Result:

enter image description here

like image 90
hitzg Avatar answered Mar 19 '23 21:03

hitzg