How to add data labels to a bar chart in Bokeh?

后端 未结 2 1650
独厮守ぢ
独厮守ぢ 2020-12-10 05:34

In the Bokeh guide there are examples of various bar charts that can be created. http://docs.bokeh.org/en/0.10.0/docs/user_guide/charts.html#id4

This code will creat

相关标签:
2条回答
  • 2020-12-10 05:46

    NOTE FROM BOKEH MAINTAINERS The portions of the answer below that refer to the bokeh.charts are of historical interest only. The bokeh.charts API was deprecated and subsequently removed from Bokeh. See the answers here and above for information on the stable bokeh.plotting API


    Yes, you can add labels to each bar of the chart. There are a few ways to do this. By default, your labels are tied to your data. But you can change what is displayed. Here are a few ways to do that using your example:

    from bokeh.charts import Bar, output_file, show
    from bokeh.sampledata.autompg import autompg as df
    from bokeh.layouts import gridplot
    
    from pandas import DataFrame
    from bokeh.plotting import figure, ColumnDataSource
    from bokeh.models import Range1d, HoverTool
    
    # output_file("bar.html")
    
    """ Adding some sample labels a few different ways.
        Play with the sample data and code to get an idea what does what.
        See below for output.
    """
    

    Sample data (new labels):

    I used some logic to determine the new dataframe column. Of course you could use another column already in df (it all depends on what data you're working). All you really need here is to supply a new column to the dataframe.

    # One method
    labels = []
    for number in df['cyl']:
        if number == 3:
            labels.append("three")
        if number == 4:
            labels.append("four")
        if number == 5:
            labels.append("five")
        if number == 6:
            labels.append("six")
        if number == 8:
            labels.append("eight")
    
    df['labels'] = labels
    

    Another way to get a new dataframe column. Again, we just need to supply df a new column to use on our bar plot.

    # Another method
    def new_labels(x):
        if x % 2 != 0 or x == 6:
            y = "Inline"
        elif x % 2 == 0:
            y = "V"
        else:
            y = "nan"
        return y
    
    df["more_labels"] = df["cyl"].map(new_labels)
    

    Now the bar chart:

    I've done it two ways. p1 just specifies the new labels. Note that because I used strings it put them in alphabetical order on the chart. p2 uses the original labels, plus adds my new labels on the same bar.

    # Specifying your labels
    p1 = Bar(df, label='labels', values='mpg',
             title="Total MPG by CYL, remapped labels, p1",
             width=400, height=400, legend="top_right")
    p2 = Bar(df, label=['cyl', 'more_labels'], values='mpg',
             title="Total MPG by CYL, multiple labels, p2", width=400, height=400,
             legend="top_right")
    

    Another way:

    Bokeh has three main "interface levels". High level charts provides quick easy access but limited functionality; plotting which gives more options; models gives even more options.

    Here I'm using the plotting interface and the Figure class that contains a rect method. This gives you more detailed control of your chart.

    # Plot with "intermediate-level" bokeh.plotting interface
    new_df = DataFrame(df.groupby(['cyl'])['mpg'].sum())
    factors = ["three", "four", "five", "six", "eight"]
    ordinate = new_df['mpg'].tolist()
    mpg = [x * 0.5 for x in ordinate]
    
    p3 = figure(x_range=factors, width=400, height=400,
                title="Total MPG by CYL, using 'rect' instead of 'bar', p3")
    p3.rect(factors, y=mpg, width=0.75, height=ordinate)
    p3.y_range = Range1d(0, 6000)
    p3.xaxis.axis_label = "x axis name"
    p3.yaxis.axis_label = "Sum(Mpg)"
    

    A fourth way to add specific labels:

    Here I'm using the hover plot tool. Hover over each bar to display your specified label.

    # With HoverTool, using 'quad' instead of 'rect'
    top = [int(x) for x in ordinate]
    bottom = [0] * len(top)
    left = []
    [left.append(x-0.2) for x in range(1, len(top)+1)]
    right = []
    [right.append(x+0.2) for x in range(1, len(top)+1)]
    cyl = ["three", "four", "five", "six", "eight"]
    source = ColumnDataSource(
        data=dict(
            top=[int(x) for x in ordinate],
            bottom=[0] * len(top),
            left=left,
            right=right,
            cyl=["three", "four", "five", "six", "eight"],
        )
    )
    
    hover = HoverTool(
        tooltips=[
            ("cyl", "@cyl"),
            ("sum", "@top")
        ]
    )
    
    p4 = figure(width=400, height=400,
                title="Total MPG by CYL, with HoverTool and 'quad', p4")
    p4.add_tools(hover)
    p4.quad(top=[int(x) for x in ordinate], bottom=[0] * len(top),
            left=left, right=right, color="green", source=source)
    p4.xaxis.axis_label = "x axis name"
    

    Show all four charts in a grid:

    grid = gridplot([[p1, p2], [p3, p4]])
    show(grid)
    

    These are the ways I am aware of. There may be others. Change whatever you like to fit your needs. Here is what running all of this will output (you'll have to run it or serve it to get the hovertool):

    0 讨论(0)
  • 2020-12-10 05:49

    Use Labelset

    Use Labelset to create a label over each individual bar

    In my example I'm using vbar with the plotting interface, it is a little bit more low level then the Charts interface, but there might be a way to add it into the Bar chart.

    from bokeh.palettes import PuBu
    from bokeh.io import show, output_notebook
    from bokeh.models import ColumnDataSource, ranges, LabelSet
    from bokeh.plotting import figure
    output_notebook()
    
    source = ColumnDataSource(dict(x=['Áætlaðir','Unnir'],y=[576,608]))
    
    x_label = ""
    y_label = "Tímar (klst)"
    title = "Tímar; núllti til þriðji sprettur."
    plot = figure(plot_width=600, plot_height=300, tools="save",
            x_axis_label = x_label,
            y_axis_label = y_label,
            title=title,
            x_minor_ticks=2,
            x_range = source.data["x"],
            y_range= ranges.Range1d(start=0,end=700))
    
    
    labels = LabelSet(x='x', y='y', text='y', level='glyph',
            x_offset=-13.5, y_offset=0, source=source, render_mode='canvas')
    
    plot.vbar(source=source,x='x',top='y',bottom=0,width=0.3,color=PuBu[7][2])
    
    plot.add_layout(labels)
    show(plot)
    

    You can find more about labelset here: Bokeh annotations

    0 讨论(0)
提交回复
热议问题