Ben
Ben

Reputation: 353

Setting x-axis label range while auto-scaling y in matplotlib

I'm finding it really difficult to achieve something that feels like it should be really simple, using matplotlib. I have a time series of 1000 data points, recorded 10s apart. I want to plot them, so that the x-axis range is correctly labelled from 0 to 10,000s. I want the y-axis values to be chosen automatically.

Whatever I try, I can't seem to get matplotlib to display any labels on the x axis other than the number of datapoints in the array (i.e. 0-1000). I have tried:

plotting twice. First letting it autoscale, then calling plt.axis() to retrieve the x and y limits, and then storing them for a second call of plt.axis([a,b,c,d]). It just plotted 0-1000. Somehow it just ignored me and reverted to 0-1000.

I tried this:

ax = plt.subplot(111)  

ax.xaxis.set_data_interval(0, 10000)

also

plt.xlim(0, 10000)

to no avail, as well as many other things I've now deleted and forgotten. I can't believe I've somehow wasted hours on this now!

Can anybody help? Thanks!

Edit: I was asked for a minimal example - here are two that illustrate the two results that I have found,

import matplotlib.pyplot as plt
tseries=[1,2,3,4,5,6,7,8,9,10]
plt.plot(tseries)
ax = plt.subplot(111)  
ax.xaxis.set_data_interval(0, 10000)
plt.show()

enter image description here

This one is just ignored

import matplotlib.pyplot as plt
tseries=[1,2,3,4,5,6,7,8,9,10]
plt.plot(tseries)
plt.xlim(0, 100)
plt.show()

enter image description here

And this one squashes all the data, keeping it in the 0-10 range of the plot.

All methods I have tried have produced one of the two results above

Basically I just want the first plot with the axes of the second.

Upvotes: 1

Views: 5368

Answers (2)

Ben
Ben

Reputation: 353

Finally found a solution that works. There's probably a better way.

x = np.arange(0.0, total_time, total_time/len(tseries))
y = np.array(tseries)
plt.plot(x.flatten(),y.flatten())

Edit:

This turned out sometimes fail, saying the lengths of x and y were not the same.
I added this hack to prevent that:

if len(x)!=len(y):
    l=min(len(x),len(y))
    x=x[:l]
    y=y[:l]

I guess it's caused by rounding errors in the "total_time/len(tseries" term when creating x.
Edit2: Mr. T has pointed out below that np.linspace() can be used to avoid the rounding error.

Upvotes: 1

Simon
Simon

Reputation: 10150

Maybe I'm misunderstanding the question, but this should be as simple as creating a X-series that contains the time values/labels you want. No need to do any limiting of the axis range:

import matplotlib.pyplot as plt
import numpy as np
import random

values = random.sample(range(0,1000), 1000)
times = np.arange(len(values)) * 10

# alternatively:
# times = np.arange(0, len(values)*10, 10)

plt.plot(times, values)

enter image description here

values has your 1000 data points. you need to create another array that contains the times associated with each of your values. In your original question you didn't specify an X array, so it was just plotting your values against index (0-9)

Because you know that each value recording happened 10 seconds apart, it should be as simple as generating a 1000 item list with the values 0-1000, and then multiplying each item by 10 to get the actual "recorded" times

Upvotes: 1

Related Questions