0

What I would like to do is simply build a scatterplot from a list of datetime objects, with time from 00:00 to 24:00 on the Y-axis and the date on the X-axis, and a point corresponding to the datetime object in a list.

After reading through as many references on the matter as I could find, doing this seems more convoluted than I first thought, and never can fit everything I need. Maybe I am just misreading the documentation on matplotlib.dates? From multiple stackoverflow posts and the corresponding documentation, you can plot just dates with values, or just times with values, or if you can manage to plot both, then you can't use the matplotlib date formatter correctly. Pandas may be the best solution from what I've seen, but it too has drawbacks, particularly with the date formatter and locators, and registering converters which seems to break other parts of matplotlib. Not to mention whether on not we should be converting the datetime objects to matplotlib.dates format, or use plt.plot, plt.scatter, or plot_dates, which all seem to work with some functions but not others. Not to mention the other bugs that have been reported with Locator.MAXTICKS etc.

So please, could someone help clear all of this up for me.

In terms of code I have many snippets from trying all of these methods, but here's one if anyone needs a jumping-off point (With comments from some of the various methods if it shines any light):

import pandas as pd
import matplotlib.pyplot as plt
import matplotlib.dates as mdates
import datetime
import random

from pandas.plotting import register_matplotlib_converters
register_matplotlib_converters()

# Generate random datetime's
def getRandDate(i):
    randDate = '{}-{}-{}'.format(2019, random.randint(1, 12), i) #random.randint(1,28))
    randTime = '{}:{}:{}'.format(random.randint(1,23), random.randint(1,59), random.randint(1,59))
    timeStrng = randDate + ' ' + randTime
    return datetime.datetime.strptime(timeStrng, '%Y-%m-%d %H:%M:%S')

dteTms1 = [getRandDate(i) for i in range(1,28)]
dteTms2 = [getRandDate(i) for i in range(1,28)]

x_axis1, y_axis1 = zip(*[(item.date(),item.time()) for item in dteTms1])
x_axis2, y_axis2 = zip(*[(item.date(),item.time()) for item in dteTms2])

fig, ax = plt.subplots()

ax.plot(x_axis1, y_axis1, 'ro', markersize=1)
ax.plot(x_axis2, y_axis2, 'go', markersize=1)
ax.set_ylim(["00:00:00", "23:59:59"])

ax.xaxis.set_major_locator(mdates.MonthLocator())
ax.xaxis.set_major_formatter(mdates.DateFormatter('%Y-%m-%d')) 
ax.xaxis.set_minor_locator(mdates.DayLocator())
#ax.yaxis.set_major_locator(mdates.HourLocator()) # This breaks the y axis
#ax.yaxis.set_major_formatter(mdates.DateFormatter('%H:%M'))

fig.autofmt_xdate()
plt.show()

I can also add the list of links to all the SO posts and documentation if anyone would like it. And lastly, thank you for your help.

1 Answer 1

1

Matplotlib provides no capabilities to format times only. So you need to plot times on an arbitrary day instead. Let's say we pick the first of january 1900. Then the example might look like this:

import matplotlib.pyplot as plt
import matplotlib.dates as mdates
import datetime
import random

from pandas.plotting import register_matplotlib_converters
register_matplotlib_converters()

# Generate random datetime's
def getRandDate(i):
    randDate = '{}-{}-{}'.format(2019, random.randint(1, 12), i) #random.randint(1,28))
    randTime = '{}:{}:{}'.format(random.randint(1,23), random.randint(1,59), random.randint(1,59))
    timeStrng = randDate + ' ' + randTime
    return datetime.datetime.strptime(timeStrng, '%Y-%m-%d %H:%M:%S')

dteTms1 = [getRandDate(i) for i in range(1,28)]
dteTms2 = [getRandDate(i) for i in range(1,28)]

x_axis1, y_axis1 = zip(*[(item.date(),item.time()) for item in dteTms1])
x_axis2, y_axis2 = zip(*[(item.date(),item.time()) for item in dteTms2])


dday = datetime.datetime(1900,1,1)
y_axis1 = [datetime.datetime.combine(dday, t) for t in y_axis1]
y_axis2 = [datetime.datetime.combine(dday, t) for t in y_axis2]

fig, ax = plt.subplots()

ax.plot(x_axis1, y_axis1, 'ro', markersize=1)
ax.plot(x_axis2, y_axis2, 'go', markersize=1)
ax.set_ylim([dday, dday+datetime.timedelta(days=1)])

ax.xaxis.set_major_locator(mdates.MonthLocator())
ax.xaxis.set_major_formatter(mdates.DateFormatter('%Y-%m-%d')) 
ax.xaxis.set_minor_locator(mdates.DayLocator())
ax.yaxis.set_major_locator(mdates.HourLocator())
ax.yaxis.set_major_formatter(mdates.DateFormatter('%H:%M'))

fig.autofmt_xdate()
plt.show()

enter image description here

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

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.