2

For data analysis, I would like to create a graph with grey striped background. Whether the background is grey or white depends on the value (1 or 0) in a different array. The figure looks like this:

enter image description here

import matplotlib.patches as patches

idx = np.linspace(0, nr_burst, nr_burst)
x = total #length nr_burst 
y = tide #zeros and ones of length nr_burst

fig, ax = plt.subplots(1, figsize=(15,5))
ax.plot(idx, x)
rect_height = np.max(x)
rect_width = 1

for i, draw_rect in enumerate(y):
    if draw_rect:
        rect = patches.Rectangle(
            (i, 0),
            rect_width,
            rect_height,
            linewidth=1,
            edgecolor='lightgrey',
            facecolor='lightgrey',
            fill=True
        )
        ax.add_patch(rect)

plt.show();

However, I would like the x-axis to give the dates instead of the index of the data. When I tried replacing idx with dates (a datetime.datetime object of length nr_burst), it gave me the error: float() argument must be a string or a number, not 'datetime.datetime'.

This was the code:

import matplotlib.patches as patches

idx = dates #with length nr_burst as well
x = total #length nr_burst 
y = tide #zeros and ones of length nr_burst

fig, ax = plt.subplots(1, figsize=(15,5))
ax.plot(idx, x)
rect_height = np.max(x)
rect_width = 1

for i, draw_rect in enumerate(y):
    if draw_rect:
        rect = patches.Rectangle(
            (dates[i], 0),
            rect_width,
            rect_height,
            linewidth=1,
            edgecolor='lightgrey',
            facecolor='lightgrey',
            fill=True
        )
        ax.add_patch(rect)

plt.show();

I hope I am being clear enough in the explanation what I want to achieve.

unutbu
  • 842,883
  • 184
  • 1,785
  • 1,677

1 Answers1

0

Your code could be fixed by converting dates to datenums:

import matplotlib.dates as mdates
datenums = mdates.date2num(dates)

and then defining the Rectangles using datenums:

patches.Rectangle((datenums[i], 0),...)

For example,

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

nr_burst = 50
dates = (np.array(['2000-01-01'], dtype='datetime64[D]') 
         + ((np.random.randint(1, 10, size=nr_burst).cumsum()).astype('<timedelta64[D]')))
idx = dates #with length nr_burst as well
x = np.random.random(nr_burst).cumsum() #length nr_burst 
y = np.random.randint(2, size=nr_burst) #zeros and ones of length nr_burst
datenums = mdates.date2num(dates)

fig, ax = plt.subplots(1, figsize=(15,5))
ax.plot(idx, x)
rect_height = np.max(x)
rect_width = 1

for i, draw_rect in enumerate(y):
    if draw_rect:
        rect = patches.Rectangle(
            (datenums[i], 0),
            rect_width,
            rect_height,
            linewidth=1,
            edgecolor='lightgrey',
            facecolor='lightgrey',
            fill=True
        )
        ax.add_patch(rect)

plt.show()

enter image description here

Alternatively, you could use ax.axvspan to create the hightlighted regions:

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

nr_burst = 50
dates = (np.array(['2000-01-01'], dtype='datetime64[D]') 
         + ((np.random.randint(1, 10, size=nr_burst).cumsum()).astype('<timedelta64[D]')))
idx = dates #with length nr_burst as well
x = np.random.random(nr_burst).cumsum() #length nr_burst 
y = np.random.randint(2, size=nr_burst) #zeros and ones of length nr_burst
datenums = mdates.date2num(dates)

fig, ax = plt.subplots(1, figsize=(15,5))
ax.plot(idx, x)

for datenum, yi in zip(datenums, y):
    if yi:
        ax.axvspan(datenum, datenum+1, facecolor='red', alpha=0.5)

plt.show()

enter image description here

unutbu
  • 842,883
  • 184
  • 1,785
  • 1,677
  • I tried the first one and it did not work, it still only shows the data without grey patches. When I print (dates) en (datenums), I get very odd values for datenums. 736570.5 etc. My (dates) look like datetime.datetime(2017, 9, 19, 11, 41) etc. – Rieneke van Noort May 22 '18 at 11:31