How to plot Horizontal Bar Chart in Bokeh (Python)

2020-03-29 12:07发布

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')

enter image description here

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)

enter image description here

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

Can anyone help modify this further?

4条回答
不美不萌又怎样
2楼-- · 2020-03-29 12:44

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")
查看更多
Deceive 欺骗
3楼-- · 2020-03-29 12:48

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)

enter image description here

查看更多
走好不送
4楼-- · 2020-03-29 12:56

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.

查看更多
在下西门庆
5楼-- · 2020-03-29 12:57

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

查看更多
登录 后发表回答