2

I've found a way to draw a line (not necessary vertical or horizontal) in a matplotlib plot: This recommends using

plt.plot([2, 3], [25, 10])

However that does not work with plot with datetimes on the x axis.

I'm getting "ValueError: ordinal must be >= 1" with all the attempts in the following code.

import matplotlib.pyplot as plt
from calendar import monthrange
import datetime

def get_datetime_range(year, month): # Create a list with all days in a month
    nb_days = monthrange(year, month)[1]
    return [datetime.date(year, month, day) for day in range(1, nb_days+1)]    

# Create sample data
date = get_datetime_range(2017, 9)
value = [d.day % 12 for d in date]

# Draw
plt.plot(date, value)

plt.axvline(date[10], color='r', zorder=0) # Vertical line works

m = len(date)-1
print("Draw line from [%s, %s] to [%s, %s]." % (date[0], value[0], date[m], value[m]))

# The following does NOT work

plt.plot_date([date[0], value[0]], 
              [date[m], value[m]]) # Gives ValueError: ordinal must be >= 1

#plt.plot([date[10], 1], 
#         [date[25], 20])


#plt.plot_date([date2num(date[0]), value[0]], 
#              [date2num(date[m]), value[m]])

#plt.plot([2, 3], [25, 10])

plt.plot()

I also tried converting the datetimes to number with date2num without success (the same error):

from matplotlib.dates import date2num

dateNum = [date2num(d) for d in date]
plt.plot(dateNum, value) # Works

plt.axvline(date[10], color='r', zorder=0) # Works

plt.plot_date([date2num(date[0]), value[0]],  
              [date2num(date[m]), value[m]]) # Gives ValueError: ordinal must be >= 1

Any help?

2 Answers 2

0

The problem arises because you have got the order of your coordinates slightly wrong. With:

plt.plot_date([date[0], value[0]], 
              [date[m], value[m]])

You are saying that your x coordinates are date[0] and value[0]. Whereas your x coordinates are actually date[0] and date[m]. Therefore, you should use:

plt.plot_date([date[0],date[m]],
              [value[0], value[m]])

The full code:

def get_datetime_range(year, month): # Create a list with all days in a month
    nb_days = monthrange(year, month)[1]
    return [datetime.date(year, month, day) for day in range(1, nb_days+1)]

# Create sample data
date = get_datetime_range(2017, 9)
value = [d.day % 12 for d in date]

# Draw
plt.plot(date, value)

plt.axvline(date[10], color='r', zorder=0) # Vertical line works

m = len(date)-1
print("Draw line from [%s, %s] to [%s, %s]." % (date[0], value[0], date[m], value[m]))

# changes were made here
plt.plot_date([date[0], date[m]], [value[0], value[m]], fmt='-', color='r')

plt.show()

Gives the following graph:

enter image description here

Sign up to request clarification or add additional context in comments.

Comments

0

The format is plot([x1, x2, x3, ...], [y1, y2, y3, ...]). In your code you have plot_date([x1, y1], [x2, y2]), which is incorrect.

replacing your code with:

plt.plot_date([date[0], date[m]], 
              [value[0], value[m]])

solves the problem.

Note, however, that the default behavior of plot_date() is to plot points (fmt='o') and not a line. If you want a line, as your code implies, you need to change the format argument:

plt.plot_date([date[0], date[m]], 
              [value[0], value[m]], fmt='-')

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.