简体   繁体   中英

How to plot Horizontal Bar Chart in Bokeh (Python)

I have this data:

data = {'Cities': {'Des_Moines': 80.0, 'Lubbock': -300.0, 'Minneapolis': 85.7,
                        'Orange_County': 80.0, 'Salt_Lake_City': 81.8, 'San_Diego': 80.0, 
                        'San_Francisco': -400.0, 'Troy': -400.0, 'Wilmington': -300.0}}

I have plotted this using Seaborn and it looks great.

df_data = pd.DataFrame(data).sort_values('Cities', ascending=False)
sns.barplot(x='Cities', y=df_data.index, data=df_data, label='Cities', palette='Greens')

在此输入图像描述

However, I'll like to embed this is a Flask web app using Bokeh .

I couldn't find an horizontal barplot in Bokeh . Even flipping the x and y axis do not seem to work. This is what I've done: * Transposed df_data from 9x1 to 1x9 . Yet, I'm still not getting anything remotely nice.

bar = Bar(df_data.transpose(), df_data.columns.tolist(), stacked=False, responsive=True)

script, div = components(bar)

在此输入图像描述

Notice that I still do not have Horizontal and my category axis is messed up.

Can anyone help modify this further?

It's pretty easy to do with rect glyphs. Note that when you set the y_range with categorical values, the indexing of these in the bokeh plot starts at 1. That's why the counter "j" starts at 1.

import numpy as np
import pandas as pd
from bokeh.plotting import figure, show
from bokeh.models import Range1d

data = {'Cities': {'Des_Moines': 80.0, 'Lubbock': -300.0, 'Minneapolis': 85.7,
                        'Orange_County': 80.0, 'Salt_Lake_City': 81.8, 'San_Diego': 80.0, 
                        'San_Francisco': -400.0, 'Troy': -400.0, 'Wilmington': -300.0}}
#df_data = pd.DataFrame(data).sort_values('Cities', ascending=False)
df_data = pd.DataFrame(data).sort(columns='Cities',ascending=False)

this_series = df_data.loc[:,'Cities']

p = figure(width=800, height=600, y_range=this_series.index.tolist())

p.background_fill = "#EAEAF2"

p.grid.grid_line_alpha=1.0
p.grid.grid_line_color = "white"

p.xaxis.axis_label = 'xlabel'
p.xaxis.axis_label_text_font_size = '14pt'
p.xaxis.major_label_text_font_size = '14pt'
#p.x_range = Range1d(0,50)
#p.xaxis[0].ticker=FixedTicker(ticks=[i for i in xrange(0,5,1)])

p.yaxis.major_label_text_font_size = '14pt'
p.yaxis.axis_label = 'ylabel'

p.yaxis.axis_label_text_font_size = '14pt'


j = 1
for k,v in this_series.iteritems():
  print k,v,j
  p.rect(x=v/2, y=j, width=abs(v), height=0.4,color=(76,114,176),
    width_units="data", height_units="data")
  j += 1

show(p)

在此输入图像描述

You can go for the low level and reconstruct an horizontal bar plot using rect or quad glyphs . The above code is tentative and lack cities labels on y axis (no more time now...). But I hope this can help.

data = {'Cities': {'Des_Moines': 80.0, 'Lubbock': -300.0, 'Minneapolis': 85.7,
                    'Orange_County': 80.0, 'Salt_Lake_City': 81.8, 'San_Diego': 80.0, 
                    'San_Francisco': -400.0, 'Troy': -400.0, 'Wilmington': -300.0}}

from bokeh.plotting import figure, show
from bokeh.models import Range1d
from bokeh.palettes import Greens9
import numpy as np

cities = data['Cities']

p = figure(width=400, height=400)

bottom = -1
ii = -1
for k,v in cities.iteritems():
    bottom = bottom+1
    top    = bottom+1
    left   = 0
    right  = cities[k]
    ii += 1
    p.quad(top=top, bottom=bottom, left=left,
         right=right, color=Greens9[ii]) #"#B3DE69")

min_city = min(cities, key=cities.get)
max_city = max(cities, key=cities.get)
p.x_range = Range1d(start=cities[min_city], end=cities[max_city])

show(p)

# Can be done with rect glyph:
#p = figure(width=400, height=400)
#p.rect(x=[1, 2, 3], y=[1, 2, 3], width=0.2, height=40, color="#CAB2D6",
#       angle=np.pi/2, height_units="screen")

AFAIK there isn't one. This is the closest mention to it that I know of being #1856 . For now only vertical bar charts are available:

Bar Graph aka Horizontal Bar Graph (we currently don't have a chartfor)

Column Graph aka Vertical Bar Graph (currently Bar)

Side Note: Transposing the data will work as you have tried, that is expected.

I think there is none. One hack could be to use a custom css with rotate() http://www.w3schools.com/css/css3_2dtransforms.asp

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