开发者

matplotlib: plot durations with nice and dynamic formatting

I need to make a dates (on x) vs. durations of time (on y) plots and need to have smart formatting for the y axis. My data is of the format: '0:00:02.994000' (0 hrs, 0 min, 2 seconds and 994000 microseconds).

The data could range from as little as a few seconds to more than 12 hours, I'd guess, though generally for any given plot most data points would be in the same units (sec, min, or hr).

The problem is, sometimes there will be outliers that are in a different unit. E.g., there may be a plot in which most durations are within 1-3 hrs, but now and then there is a datapoint of 5 minutes, or even 30 seconds. Or it could be another one with mostly datapoints in minutes, but an occasional long or short one in hours or seconds.

I want to pick a good (dynamic) way to format the y axis. There are two issues:

1) Should I analyze the data to see what units the majority of datapoints are in and then use that as the y axis units? That is, if most are durations of minutes, then the y axis should be given in minutes. If most are in hours, the y axis should be hours, etc... This way the formatting is most appropriate for the type of data displayed.

2) If a plot's y units are given in terms of minutes (because of point #1), but a user wants to zoom in (with the zoom tool) on a datapoint that is only a few seconds, I'd like the formatter to change the y scaling to be i开发者_运维技巧n terms of seconds. I don't want to have express durations on the y axis as anything like "0.0335" minutes, but rather "2 seconds".

Any suggestions for how to approach this would be appreciated. Thanks, Che


You could register an event handler that mucks with the y data based on ylim.

fig = plt.figure()
ax = fig.add_subplot(111)
ylim = ax.get_ylim()
scale = get_scale(ylim)
def tweak_y(event):
    new_ylim = ax.get_ylim() 
    if new_ylim == ylim:
        return
    ylim = new_ylim
    if get_scale(ylim) != scale:
        # tweak ydata and replot
        pass

cid = fig.canvas.mpl_connect('draw_event', tweak_y)


The way I do this is to use the datetime.timedelta string formatting, you can create the formatter like this:

def timeTicks(x, pos):
    d = datetime.timedelta(seconds=x)
    return str(d)
formatter = matplotlib.ticker.FuncFormatter(timeTicks)

Which can be applied to an axis using ax.xaxis.set_major_formatter(formatter), this will scale when the user zooms. Note that this does not address the majority issue, but might be useful for others in similar situations.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜