问题
I am trying to get two stacked bar charts side by side but cannot figure it out.
Here's an example df:
Field Issue
Police Budget cuts
Research Budget cuts
Police Time consuming
Banking Lack of oversight
Healthcare Lack of support
Research Bureaucracy
Healthcare Bureaucracy
Banking Mistrust
What I want is a stacked bar chart of of field first. It will have a height of 8 broken down by 2 police, 2 x research etc. Then I want a stacked bar chart of Issue next to the first chart. This second one will have a height of 8 and be stacked by 2 x budget cuts, 1 x time consuming, 1 x lack of oversight etc.
I have tried:
to get the stacked bar chart of all fields:
trace1 = go.Bar(
x = df.Field.unique(),
y = df.Field.value_counts(),
name='Total Amount of roles'
)
to get a stacked bar chart of Budget cuts (then replicate for other issues):
trace2 = go.Bar(
x = df.Field.unique(),
y = df[df['Issue'] == 'Budget cuts'].Field.value_counts(),
name='Budget cuts'
)
data = [trace1, trace2]
layout = go.Layout(barmode='stack')
fig = go.Figure(data=data, layout=layout)
py.plot(fig, filename='test.html')
But the above code stacks the two graphs onto one. I want trace 1 stacked and trace 2 stacked. I also want this integrated into Dash and not plotly on it's own but that would be secondary to be honest. Would appreciate any help!
回答1:
EDIT - after a short dialouge in the comments, this is my latest suggestion:
Here's a possible solution with the count of each ocurence of each category stacked per column ( Field or Issue):
Plot:
Code:
As you can see it's not very flexible since you'll have to add one go.Bar
object for each category (Banking, Police etc). But if the plot above is what you're looking for, I'll sort out that part too.
# import
import pandas as pd
import numpy as np
import plotly.graph_objs as go
from plotly.offline import download_plotlyjs, init_notebook_mode, plot, iplot
init_notebook_mode(connected=True)
#%qtconsole
# sample data
Field = ['Police', 'Research', 'Police', 'Banking', 'Healthcare', 'Research', 'Healthcare', 'Banking']
Issue = ['Budget cuts', 'Budget cuts', 'Time consuming', 'Lack of oversight', 'Lack of support', 'Bureaucracy', 'Bureaucracy', 'Mistrust']
# Put the lists in a pandas dataframe for
# easy grouping and indexing
df = pd.DataFrame([Field, Issue]).T
df.columns = ['Field', 'Issue']
grField = df.groupby('Field').count()
grIssue = df.groupby('Issue').count()
dfgr = pd.concat([grField, grIssue], axis = 1, sort = False)
dfgr = dfgr.T
# Make one go.Bar() object for each category
# for corresponing Field / Issue
trace1 = go.Bar(
x = ['Issue'],
#y = [dfgr['Field']],
y = [dfgr['Banking'].loc['Issue']],
name='Banking')
trace2 = go.Bar(
x = ['Issue'],
#y = [dfgr['Field']],
y = [dfgr['Healthcare'].loc['Issue']],
name='Healthcare')
trace3 = go.Bar(
x = ['Issue'],
#y = [dfgr['Field']],
y = [dfgr['Police'].loc['Issue']],
name='Police')
trace4 = go.Bar(
x = ['Issue'],
#y = [dfgr['Field']],
y = [dfgr['Research'].loc['Issue']],
name='Research')
trace5 = go.Bar(
x = ['Field'],
#y = [dfgr['Field']],
y = [dfgr['Budget cuts'].loc['Field']],
name='Budget cuts')
trace6 = go.Bar(
x = ['Field'],
#y = [dfgr['Field']],
y = [dfgr['Bureaucracy'].loc['Field']],
name='Bureaucracy')
trace7 = go.Bar(
x = ['Field'],
#y = [dfgr['Field']],
y = [dfgr['Lack of oversight'].loc['Field']],
name='Lack of oversight')
trace7 = go.Bar(
x = ['Field'],
#y = [dfgr['Field']],
y = [dfgr['Lack of oversight'].loc['Field']],
name='Lack of oversight')
trace8 = go.Bar(
x = ['Field'],
#y = [dfgr['Field']],
y = [dfgr['Lack of support'].loc['Field']],
name='Lack of support')
trace9 = go.Bar(
x = ['Field'],
#y = [dfgr['Field']],
y = [dfgr['Mistrust'].loc['Field']],
name='Mistrust')
trace10 = go.Bar(
x = ['Field'],
#y = [dfgr['Field']],
y = [dfgr['Time consuming'].loc['Field']],
name='Time consuming')
# gather data and set up layout
#data = [trace1, trace2, trace3, trace4, trace5, trace6, trace7, trace8, trace9, trace10]
data = [trace10, trace9, trace8, trace7, trace6, trace5, trace4, trace3, trace2, trace1]
layout = go.Layout(barmode='stack', title = 'Stacked bar chart from single column')
# Build figure
fig = go.Figure(data=data, layout=layout)
# PLot figure
iplot(fig, filename='test.html')
回答2:
Snippets of working code, in case this is what you need:
import plotly.graph_objects as go
x=['a','b','c','d']
fig = go.Figure(go.Bar(x =x, y=[2,5,1,9], name='Montreal',
base = 0, width = 0.2, offset = 0.0,
marker = dict(color = 'rgb(0,120,255)')))
fig.add_trace(go.Bar(x=x, y=[1, 4, 9, 16], name='Ottawa',
width = 0.2, offset = -0.2,
marker = dict(color = 'rgb(250,60,0)')))
fig.add_trace(go.Bar(x=x, y=[6, 8, 4.5, 8], name='Toronto',
width = 0.2, offset = -0.2,
marker = dict(color = 'rgb(250,130,0)')))
fig.update_layout(barmode='stack', xaxis={'categoryorder':'array', 'categoryarray':['d','a','c','b']})
fig.show()
an alternate layout:
change: base,offset of second figure
import plotly.graph_objects as go
x=['a','b','c','d']
fig = go.Figure(go.Bar(x =x, y=[2,5,1,9], name='Montreal',
base = 0, width = 0.2, offset = 0.0,
marker = dict(color = 'rgb(0,120,255)')))
fig.add_trace(go.Bar(x=x, y=[1, 4, 9, 16], name='Ottawa',
width = 0.2, offset = -0.4, base=0,
marker = dict(color = 'rgb(250,60,0)')))
fig.add_trace(go.Bar(x=x, y=[6, 8, 4.5, 8], name='Toronto',
width = 0.2, offset = -0.2,
marker = dict(color = 'rgb(250,130,0)')))
fig.update_layout(barmode='stack', xaxis={'categoryorder':'array', 'categoryarray':['d','a','c','b']})
fig.show()
来源:https://stackoverflow.com/questions/55238122/plotly-dash-want-two-stacked-bar-charts-side-by-side-from-single-df-column