简体   繁体   中英

Plotting Weeks with Bokeh Datetime Axis

I am trying to make a bar chart from Bokeh with a Datetime x-axis. I am using several time resolutions, and I can get all of them to work except for the weeks. I have a pandas dataframe that looks like this (I added the 'Week' column for reference, it shouldn't stay)

Timestamp   ResultID
2017-12-03  106
2017-11-26  381
2017-11-19  406
2017-11-12  662
2017-11-05  656
2017-10-29  638
2017-10-22  429
2017-10-15  784

Output with date

You can see that the labels are misaligned and sometimes missing. It looks like Bokeh is always displaying the first day of the month regardless of if it is the first day of the week or not. this then shifts the other labels out of position. I can't seem to find any documentation that would help to do this. I also can't use a categorical axis because the way that I am setting ranges to only show the 7 most recent bins will break. I've also tried changing the format of the labels to show the calendar week labels but no luck there either. Any ideas on how to get the labels to match with the appropriate columns?



    bintime = 'W'
    bins = {'h' : '%Y-%m-%d %H:%M', 'D' : '%F', 'W' : '%F', 'M' : '%Y-%m'}
    widths = {'h' : 3600000, 'D' : 86400000, 'W' : 604800000, 'M' : 2419200000}
    pad = 0.9

    source = ColumnDataSource(df)

    now = np.datetime64(datetime.datetime.now())

    if bintime == 'M':
        padspace = now + np.timedelta64(1*30, 'D')
        dispdelta = now - np.timedelta64(7*30, 'D')
    else:
        padspace = now
        dispdelta = now - np.timedelta64(7, bintime)

    ranges = ['hours', 'days', 'months']

    #xrange = df.DT.tolist()
    xrange = (dispdelta, padspace)

    output = figure(plot_height=300, width=800, title="MPL Output", x_range=xrange, tools ='xpan,reset,xzoom_in,xzoom_out')
    output.vbar(x='Timestamp', top='ResultID', width=widths[bintime]*pad, source=source)
    output.xaxis.formatter=DatetimeTickFormatter(hours=bins[bintime], days=bins[bintime], months=bins[bintime])
    show(output)

SO I figured it out, posting in case someone else has a similar problem.

You need to modify the ticker method on the xaxis. When a your x_axis_type is a datetime, Bokeh automatically uses the DatetimeTicker method . This finds the type that best fits the data range, which in this case is a DaysTicker that adds ticks on the 1st, 8th, 15th, and 22nd of the month. This would be fine for a line or other area graph, but to get it to line up with the weeks you need to force the ticks to line up with the bars. You can do this by:

tickers = pd.to_datetime(df.index.values).astype(int) / 10**6

or taking your datetime field and converting it to a ms epoch integer (the 10**6 is because a numpy datetime is in nanoseconds), and then adding output.xaxis.ticker = FixedTicker(ticks = tickers)

This forces the ticks to align with the centers of the bars. This way, however you resample your dataframe, the labels will match automatically.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM