Bokeh patches plot with dates as x-axis shifts the ticks one to the right

后端 未结 1 1756
小蘑菇
小蘑菇 2021-01-13 14:55

I\'m trying to adapt the brewer example (http://docs.bokeh.org/en/latest/docs/gallery/stacked_area.html) to my needs. One of the things I\'d like is to have dates at the x-a

相关标签:
1条回答
  • 2021-01-13 15:47

    Well, if you have a list of strings as your x axis, then apparently the count starts at 1, then you have to modify your x data for the plot to start at 1. Actually the brewer example (http://docs.bokeh.org/en/latest/docs/gallery/stacked_area.html) has a range from 0 to 19, so it has 20 data points not 19 like your timesteps list. I modified the x input for the plot as : data['x'] = np.arange(1,N+1) to start from 1 to N. And I added one more day to your list: timesteps = [str(x.date()) for x in pd.date_range('1950-01-01', '1951-08-01', freq='MS')] Here is the complete code:

    import numpy as np
    import pandas as pd
    
    from bokeh.plotting import figure, show, output_file
    from bokeh.palettes import brewer
    
    N = 20
    categories = ['y' + str(x) for x in range(10)]
    data = {}
    data['x'] = np.arange(1,N+1)
    for cat in categories:
        data[cat] = np.random.randint(10, 100, size=N)
    
    df = pd.DataFrame(data)
    df = df.set_index(['x'])
    
    def stacked(df, categories):
        areas = dict()
        last = np.zeros(len(df[categories[0]]))
        for cat in categories:
            next = last + df[cat]
            areas[cat] = np.hstack((last[::-1], next))
            last = next
        return areas
    
    areas = stacked(df, categories)
    
    colors = brewer["Spectral"][len(areas)]
    
    x2 = np.hstack((data['x'][::-1], data['x']))
    
    
    timesteps = [str(x.date()) for x in pd.date_range('1950-01-01', '1951-08-01', freq='MS')]
    p = figure(x_range=bokeh.models.FactorRange(factors=timesteps), y_range=(0, 800))
    
    p.grid.minor_grid_line_color = '#eeeeee'
    
    p.patches([x2] * len(areas), [areas[cat] for cat in categories],
              color=colors, alpha=0.8, line_color=None)
    p.xaxis.major_label_orientation = np.pi/4
    bokeh.io.show(p)
    

    And here is the output:

    UPDATE

    You can leave data['x'] = np.arange(0,N) from 0 to 19, and then use offset=-1 inside FactorRange, i.e. figure(x_range=bokeh.models.FactorRange(factors=timesteps,offset=-1),...

    Update version bokeh 0.12.16

    In this version I am using datetime for x axis which has the advantage of nicer formatting when zooming in.

    import numpy as np
    import pandas as pd
    
    from bokeh.plotting import figure, show, output_file
    from bokeh.palettes import brewer
    
    timesteps = [x for x in pd.date_range('1950-01-01', '1951-07-01', freq='MS')]
    N = len(timesteps)
    cats = 10
    
    df = pd.DataFrame(np.random.randint(10, 100, size=(N, cats))).add_prefix('y')
    
    def  stacked(df):
        df_top = df.cumsum(axis=1)
        df_bottom = df_top.shift(axis=1).fillna({'y0': 0})[::-1]
        df_stack = pd.concat([df_bottom, df_top], ignore_index=True)
        return df_stack
    
    areas = stacked(df)
    colors = brewer['Spectral'][areas.shape[1]]
    
    
    x2 = np.hstack((timesteps[::-1], timesteps))
    
    p = figure( x_axis_type='datetime', y_range=(0, 800))
    p.grid.minor_grid_line_color = '#eeeeee'
    
    p.patches([x2] * areas.shape[1], [areas[c].values for c in areas],
              color=colors, alpha=0.8, line_color=None)
    p.xaxis.formatter = bokeh.models.formatters.DatetimeTickFormatter(
        months=["%Y-%m-%d"])
    p.xaxis.major_label_orientation = 3.4142/4
    output_file('brewer.html', title='brewer.py example')
    
    show(p)
    
    0 讨论(0)
提交回复
热议问题