gypaetus
gypaetus

Reputation: 7349

Non monotonic x range in matplotlib

I would like to display a graph as a function of fractional hours, where the x axis jumps from 24 to 0 hours. However the plotted quantity should be joined smoothly accross date boundaries. I could use different time units in the x axis that increase monotonically, but I would like to display the hours at integer tick locations in the x axis, how could I do that?

hours = [19,20.5,21.5,22.5,23.5,0.5,1.5,2.5,3,4]
list1 = [random.randint(1,10) for x in range(10)]
plt.plot(hours, list1)

Upvotes: 2

Views: 992

Answers (2)

tacaswell
tacaswell

Reputation: 87486

I assume the hours list is the result of stripping the time out of a more complete date structure?

If you convert the dates datetime objects (including the day information so they really are montonic), you can then directly plot list1 against the dates. You can then

import datetime

d = datetime.datetime.now()
delta = datetime.timedelta(hours=1)
dates = [d]
for j in range(20):
    dates.append(dates[-1] + delta)

date_list = dates
list1 = rand(len(dates))
figure()
ax = gca()
ax.plot(date_list,list1)
ax.xaxis.set_major_locator(
    matplotlib.dates.HourLocator()
)
ax.xaxis.set_major_formatter(
    matplotlib.dates.DateFormatter('%H')
)

adapted from here

result of code

Upvotes: 2

Lev Levitsky
Lev Levitsky

Reputation: 65811

Well, this is very dirty, and I'd try going with the other answer now that it's posted, but (in ipython --pylab):

In [1]: def monotonic_hours(h):
    hours = h[:]
    for i, _ in enumerate(h[1:], 1):
        while hours[i-1] > hours[i]:
            hours[i] += 24
    return hours
   ...: 

In [2]: %paste
hours = [19,20.5,21.5,22.5,23.5,0.5,1.5,2.5,3,4]
list1 = [random.randint(1,10) for x in range(10)]

## -- End pasted text --

In [3]: plot(monotonic_hours(hours), list1)
Out[3]: [<matplotlib.lines.Line2D at 0x3271810>]

In [4]: xticks(xticks()[0], [int(h%24) for h in xticks()[0]])

enter image description here

Note: this is accurate if the default xticks are at integer positions, otherwise you can do something like

ticks = sorted(set(int(round(t)) for t in xticks()[0]))
xticks(ticks, [h%24 for h in ticks])

Note 2: without ipython you can call everything on plt.

Upvotes: 2

Related Questions