Plotly: How to create a barchart using group by? - python

I have a dataset as below:
import pandas as pd
data = dict(Pclass=[1,1,2,2,3,3],
Survived = [0,1,0,1,0,1],
CategorySize = [80,136,97,87,372,119] )
I need to create a barchart using plotly in python, which is grouped by Pclass. in each group, i have 2 columns for Survived=0 and Survived=1 and in Y axis i should have the CategorySize. Therefore, i must have 6 bars which are in 3 groups.
Here is what i have tried:
import plotly.offline as pyo
import plotly.graph_objects as go
data = [ go.Bar( x = PclassSurvived.Pclass, y = PclassSurvived.CategorySize ) ]
layout = go.Layout(title= 'Pclass-Survived', xaxis = dict(title = 'Pclass'), yaxis = dict(title = 'CategorySize'),barmode='group' )
fig = go.Figure(data = data, layout = layout)
pyo.plot( fig, filename='./Output/Pclass-Survived.html')
But, it is not what i need.

This could be easily done with Pandas's groupby and Plotly Express.
You should group your data by Pclass and Survived columns, and apply the sum aggregate function to the CategorySize column.
This way you'll get 6 groups, with their aggregate values, and you can easily plot for each group a pair of bar charts (side-byside) thanks to the barmode attribute (by using the 'group' value), you can read more about it in the documentation.
The code:
import pandas as pd
import plotly.express as px
data = pd.DataFrame(
dict(
Pclass=[1, 1, 2, 2, 3, 3],
Survived=[0, 1, 0, 1, 0, 1],
CategorySize=[80, 136, 97, 87, 372, 119],
)
)
Now you group the data:
grouped_df = data.groupby(by=["Pclass", "Survived"], as_index=False).agg(
{"CategorySize": "sum"}
)
And convert the Survived column values to strings (so plotly treat it as a discrete variable, rather than numeric variable):
grouped_df.Survived = grouped_df.Survived.map({0: "Died", 1: "Survived",})
Now, you should have:
Pclass
Survived
CategorySize
0
1
Died
80
1
1
Survived
136
2
2
Died
97
3
2
Survived
87
4
3
Died
372
5
3
Survived
119
Finally, you visualize your data:
fig = px.bar(
data_frame=grouped_df,
x="Pclass",
y="CategorySize",
color="Survived",
barmode="group",
)
fig.show()

I'm having trouble with your sample dataset. PclassSurvived.Pclass and PclassSurvived.CategorySize are not defined, and it's not 100% clear to me what you would like to accomplish here. But judging by your explanations and the structure of your dataset, it seems that this could get you somewhere:
Plot 1:
Code 1:
# imports
from plotly.subplots import make_subplots
import plotly.figure_factory as ff
import plotly.graph_objs as go
import pandas as pd
import numpy as np
data = dict(Pclass=[1,1,2,2,3,3],
Survived = [0,1,0,1,0,1],
CategorySize = [80,136,97,87,372,119] )
df=pd.DataFrame(data)
s0=df.query('Survived==0')
s1=df.query('Survived==1')
#layout = go.Layout(title= 'Pclass-Survived', xaxis = dict(title = 'Pclass'), yaxis = dict(title = 'CategorySize'),barmode='group' )
fig = go.Figure()
data=data['Pclass']
fig.add_trace(go.Bar(x=s0['Pclass'], y = s0['CategorySize'],
name='dead'
)
)
fig.add_trace(go.Bar(x=s1['Pclass'], y = s1['CategorySize'],
name='alive'
)
)
fig.update_layout(barmode='group')
fig.show()
Edit: You can produce the same plot using the plotly.offline module like this:
Code 2:
# Import the necessaries libraries
import plotly.offline as pyo
import plotly.graph_objs as go
import pandas as pd
# Set notebook mode to work in offline
pyo.init_notebook_mode()
# data
data = dict(Pclass=[1,1,2,2,3,3],
Survived = [0,1,0,1,0,1],
CategorySize = [80,136,97,87,372,119] )
df=pd.DataFrame(data)
#
s0=df.query('Survived==0')
s1=df.query('Survived==1')
fig = go.Figure()
data=data['Pclass']
fig.add_trace(go.Bar(x=s0['Pclass'], y = s0['CategorySize'],
name='dead'
)
)
fig.add_trace(go.Bar(x=s1['Pclass'], y = s1['CategorySize'],
name='alive'
)
)
pyo.iplot(fig, filename = 'your-library')
Alternative approach with stacked bars:
Plot 2:
Code 3:
# imports
from plotly.subplots import make_subplots
import plotly.figure_factory as ff
import plotly.graph_objs as go
import pandas as pd
import numpy as np
data = dict(Pclass=[1,1,2,2,3,3],
Survived = [0,1,0,1,0,1],
CategorySize = [80,136,97,87,372,119] )
df=pd.DataFrame(data)
s0=df.query('Survived==0')
s1=df.query('Survived==1')
#layout = go.Layout(title= 'Pclass-Survived', xaxis = dict(title = 'Pclass'), yaxis = dict(title = 'CategorySize'),barmode='group' )
fig = go.Figure()
data=data['Pclass']
fig.add_trace(go.Bar(x=s0['Pclass'], y = s0['CategorySize'],
name='dead'
)
)
fig.add_trace(go.Bar(x=s1['Pclass'], y = s1['CategorySize'],
name='alive'
)
)
df_tot = df.groupby('Pclass').sum()
annot1 = [dict(
x=xi,
y=yi,
text=str(yi),
xanchor='auto',
yanchor='bottom',
showarrow=False,
) for xi, yi in zip(df_tot.index, df_tot['CategorySize'])]
fig.update_layout(barmode='stack', annotations=annot1)
fig.show()

Related

3d animated line plot with plotly in python

I saw this 3d plot. it was animated and added a new value every day. i have not found an example to recreate it with plotly in python.
the plot should start with the value from the first row (100). The start value should remain (no rolling values). The plot should be animated in such a way that each row value is added one after the other and the x-axis expands. the following data frame contains the values (df_stocks) and Dates to plot. assigning the colors would be a great addition. the more positive the deeper the green, the more negative the darker red.
import yfinance as yf
import pandas as pd
stocks = ["AAPL", "MSFT"]
df_stocks = pd.DataFrame()
for stock in stocks:
df = yf.download(stock, start="2022-01-01", end="2022-07-01", group_by='ticker')
df['perct'] = df['Close'].pct_change()
df_stocks[stock] = df['perct']
df_stocks.iloc[0] = 0
df_stocks += 1
df_stocks = df_stocks.cumprod()*100
df_stocks -= 100
You can use a list of go.Frame objects as shown in this example. Since you want the line plot to continually extend outward, each frame needs to include data that's one row longer than the previous frame, so we can use a list comprehension like:
frames = [go.Frame(data=
## ...extract info from df_stocks.iloc[:i]
for i in range(len(df_stocks))]
To add colors to your lines depending on their value, you can use binning and labels (as in this answer) to create new columns called AAPL_color and MSFT_color that contain the string of the css color (like 'darkorange' or 'green'). Then you can pass the information from these columns using the argument line=dict(color=...) in each go.Scatter3d object.
import yfinance as yf
import numpy as np
import pandas as pd
import plotly.express as px
import plotly.graph_objects as go
stocks = ["AAPL", "MSFT"]
df_stocks = pd.DataFrame()
for stock in stocks:
df = yf.download(stock, start="2022-01-01", end="2022-07-01", group_by='ticker')
df['perct'] = df['Close'].pct_change()
df_stocks[stock] = df['perct']
df_stocks.iloc[0] = 0
df_stocks += 1
df_stocks = df_stocks.cumprod()*100
df_stocks -= 100
df_min = df_stocks[['AAPL','MSFT']].min().min() - 1
df_max = df_stocks[['AAPL','MSFT']].max().max() + 1
labels = ['firebrick','darkorange','peachpuff','palegoldenrod','palegreen','green']
bins = np.linspace(df_min,df_max,len(labels)+1)
df_stocks['AAPL_color'] = pd.cut(df_stocks['AAPL'], bins=bins, labels=labels).astype(str)
df_stocks['MSFT_color'] = pd.cut(df_stocks['MSFT'], bins=bins, labels=labels).astype(str)
frames = [go.Frame(
data=[
go.Scatter3d(
y=df_stocks.iloc[:i].index,
z=df_stocks.iloc[:i].AAPL.values,
x=['AAPL']*i,
name='AAPL',
mode='lines',
line=dict(
color=df_stocks.iloc[:i].AAPL_color.values, width=3,
)
),
go.Scatter3d(
y=df_stocks.iloc[:i].index,
z=df_stocks.iloc[:i].MSFT.values,
x=['MSFT']*i,
name='MSFT',
mode='lines',
line=dict(
color=df_stocks.iloc[:i].MSFT_color.values, width=3,
)
)]
)
for i in range(len(df_stocks))]
fig = go.Figure(
data=list(frames[1]['data']),
frames=frames,
layout=go.Layout(
# xaxis=dict(range=[0, 5], autorange=False),
# yaxis=dict(range=[0, 5], autorange=False),
# zaxis=dict(range=[0, 5], autorange=False),
template='plotly_dark',
legend = dict(bgcolor = 'grey'),
updatemenus=[dict(
type="buttons",
font=dict(color='black'),
buttons=[dict(label="Play",
method="animate",
args=[None])])]
),
)
fig.show()

Distance between title and the plot in radarplot plotly

I want to increase the distance between the title of radar plot with the plot itself but I don't know how to do it.
Reproducible code:
import pandas as pd
import numpy as np
import plotly.graph_objects as go
from plotly.subplots import make_subplots
import plotly.io as pio
pio.renderers.default = "browser"
# Create a random data frame with 4 rows and 4 columns
# Column names are M1:M4
# Row names are A, B, C, D
np.random.seed(123)
df = pd.DataFrame(
np.random.randint(0, 100, size=(4, 4)),
columns=["M1", "M2", "M3", "M4"],
index=list("ABCD")
)
# Create a list of tuples. each tuple shows the position of each
# column in the radar plot. The first element of each tuple is the
# row indicator and the second element is the column indicator.
# Number of radars to be plotted
n_rads = len(df.columns)
positions = [(i//(n_rads//2)+1, i%(n_rads//2)+1) for i in range(n_rads)]
mm_cols = df.apply(lambda x: (min(x), max(x))).values.T
# Create a figure with 2 rows and 2 columns
fig = make_subplots(
rows=2, cols=2,
specs=[
[{"type": "polar"}]*2,
[{"type": "polar"}]*2
],
subplot_titles=df.columns,
)
# add the traces to the figure
for idx, col in enumerate(df.columns):
fig.add_trace(
go.Scatterpolar(
r=df[col],
theta=df.index,
fill='toself',
name=col
),
row=positions[idx][0],
col=positions[idx][1]
)
fig.update_layout(
polar=dict(
radialaxis=dict(
visible=True,
range=mm_cols[idx]
)
),
showlegend=True
)
fig.show()
The following is the snapshot of the first radar and I show what I mean by the "distance between the title of radar plot with the plot itself":
Note that I'm using make_subplots.

Plotly is not showing all data

I get different results when trying to plot the identical data with mathplotlib and plotly. Plotly doesn't show me the whole data range.
import plotly.plotly as py
import plotly.graph_objs as go
# filter the data
df3 = df[df.line_item_returned==0][['created_at', 'line_item_price']].copy()
# remove the time part from datetime
df3.created_at = df3.created_at.dt.floor('d')
# set the datatime column as index
df3 = df3.set_index('created_at')
# Create traces
trace0 = go.Scatter(
x = df3.index,
y = df3.line_item_price.resample('d').sum().rolling(90, center=True).mean(),
mode = 'markers',
name = 'markers'
)
data = [trace0]
py.iplot(data, filename='scatter-mode')
The chart shows only the range Oct-Dec 2018.
Plotting the same data with matplotlib shows the whole data range 2016-2018:
import matplotlib.pyplot as plt
%matplotlib inline
plt.plot(df3.line_item_price.resample('d').sum().rolling(90, center=True).mean())
The index contains all data 2016-2018:
df3.line_item_price.resample('d').sum().rolling(31, center=True).mean().index
DatetimeIndex(['2015-11-18', '2015-11-19', '2015-11-20', '2015-11-21',
'2015-11-22', '2015-11-23', '2015-11-24', '2015-11-25',
'2015-11-26', '2015-11-27',
...
'2018-12-10', '2018-12-11', '2018-12-12', '2018-12-13',
'2018-12-14', '2018-12-15', '2018-12-16', '2018-12-17',
'2018-12-18', '2018-12-19'],
dtype='datetime64[ns]', name='created_at', length=1128, freq='D')
Why is this happening?
I guess it's a problem with indices.
%matplotlib inline
import plotly.offline as py
import plotly.graph_objs as go
import pandas as pd
import numpy as np
N = 2000
df = pd.DataFrame({"value":np.random.randn(N)},
index=pd.date_range(start='2015-01-01', periods=N))
# you don't really need to us `plt`
df.resample('d').sum().rolling(90, center=True).mean().plot();
But then if you want to use plotly you should use the index from the resampled Series.
df_rsmpl = df.resample('d').sum().rolling(90, center=True).mean()
trace0 = go.Scatter(x = df_rsmpl.index,
y = df_rsmpl["value"])
data = [trace0]
py.iplot(data)

How to plot a overlapped/superimposed bar chart on DASH?

I need to change stacked barchart width to be overlapped.
I found this question and solution How to plot a superimposed bar chart using matplotlib in python? and I would like to reproduce the same chart on DASH Plotly python framework.
The code is as below:
import matplotlib.pyplot as plt
import numpy as np
width = 0.8
highPower = [1184.53,1523.48,1521.05,1517.88,1519.88,1414.98,
1419.34,1415.13,1182.70,1165.17]
lowPower = [1000.95,1233.37, 1198.97,1198.01,1214.29,1130.86,
1138.70,1104.12,1012.95,1000.36]
indices = np.arange(len(highPower))
plt.bar(indices, highPower, width=width,
color='b', label='Max Power in mW')
plt.bar([i+0.25*width for i in indices], lowPower,
width=0.5*width, color='r', alpha=0.5, label='Min Power in mW')
plt.xticks(indices+width/2.,
['T{}'.format(i) for i in range(len(highPower))] )
plt.legend()
plt.show()
Question: How to edit to accomodate DASH principles?
For instance, on Dash, bar doesn't accept width=0.5*width adn alpha=0.5
Thanks.
My own code is as below:
from plotly.offline import init_notebook_mode, iplot
from plotly import graph_objs as go
init_notebook_mode(connected = True)
import pandas as pd
import numpy as np
dfb=pd.read_csv('https://www.dropbox.com/s/90y07129zn351z9/test_data.csv?dl=1', encoding="latin-1", infer_datetime_format=True, parse_dates=['date'], skipinitialspace=True)
dfb["date"]=pd.to_datetime(dfb['date'])
dfb["site"]=dfb["site"].astype("category")
cm_inc=dfb[dfb.site == 5].pivot_table(index='date', values = 'site', aggfunc = { 'site' : 'count' } )
dfb['cm_target'] = [40]*len(dfb)
dfb.to_csv('test_data.csv', index=False)
data = [
go.Bar(x=cm_inc.index, y=cm_inc['site'], name='Enroll Site A',
#base=0
),
go.Bar(x=cm_inc.index, y=dfb['cm_target'], name='Target Site A',
#base=0,
#width=0.5
)]
layout = go.Layout(
barmode='stack',
)
fig = dict(data = data, layout = layout)
iplot(fig, show_link=False)
The proposed solution by #Teoretic to use base=0 on both traces and to use barmode='stack' is not working.
Thanks.
EDIT edited answer to use new data that was added to the question
You can do overlapped barchart in Plotly by doing these 2 steps:
1) setting barmode in layout to 'stack'
2) setting base of every barchart to 0
3) small numeric value to set to X values
Also you might want to play around with:
1) Setting "width" parameter of the second barchart to the value that suits you
2) Making labels of "X" axis data more suitable to you
Sample code (run in Jupyter Notebook):
from plotly.offline import init_notebook_mode, iplot
from plotly import graph_objs as go
init_notebook_mode(connected = True)
import pandas as pd
import numpy as np
dfb=pd.read_csv('https://www.dropbox.com/s/90y07129zn351z9/test_data.csv?dl=1', encoding="latin-1", infer_datetime_format=True, parse_dates=['date'], skipinitialspace=True)
dfb["date"]=pd.to_datetime(dfb['date'])
dfb["site"]=dfb["site"].astype("category")
cm_inc=dfb[dfb.site == 5].pivot_table(index='date', values = 'site', aggfunc = { 'site' : 'count' } )
dfb['cm_target'] = [40]*len(dfb)
dfb.to_csv('test_data.csv', index=False)
# You need small int indexes for "width" and "base" = 0 trick to work
indexes = [int(i.timestamp()) / 10000 for i in cm_inc.index]
# For string dates labels
dates_indexes = [str(i) for i in cm_inc.index]
data = [
go.Bar(x=indexes,
y=dfb['cm_target'],
name='Target Site A',
base=0
),
go.Bar(x=indexes,
y=cm_inc['site'],
name='Enroll Site A',
base=0,
width=5 # Width value varies depending on number of samples in data
)
]
layout = go.Layout(
barmode='stack',
xaxis=dict(
showticklabels=True,
ticktext=dates_indexes,
tickvals=[i for i in indexes],
)
)
fig = dict(data = data, layout = layout)
iplot(fig, show_link=False)
from plotly.offline import init_notebook_mode, iplot
from plotly import graph_objs as go
init_notebook_mode(connected = True)
import pandas as pd
import numpy as np
from datetime import timedelta, datetime, tzinfo
import time
from datetime import datetime as dt
dfb=pd.read_csv('https://www.dropbox.com/s/90y07129zn351z9/test_data.csv?dl=1', encoding="latin-1", infer_datetime_format=True, parse_dates=['date'], skipinitialspace=True)
dfb["date"]=pd.to_datetime(dfb['date'])
dfb["site"]=dfb["site"].astype("category")
cm_inc=dfb[dfb.site == 5].pivot_table(index='date', values = 'site', aggfunc = { 'site' : 'count' } )
dfb['cm_target'] = [40]*len(dfb)
dfb.to_csv('test_data.csv', index=False)
# You need small int indexes for "width" and "base" = 0 trick to work
#indexes = [int(i.timestamp()) / 10000 for i in cm_inc.index]
indexes =pd.to_datetime(cm_inc.index)
# For string dates labels
#dates_indexes = [str(i) for i in cm_inc.index]
dates_indexes = pd.to_datetime(cm_inc.index)
data = [
go.Bar(x=indexes,
y=dfb['cm_target'],
name='Target Site A',
base=0
),
go.Bar(x=indexes,
y=cm_inc['site'],
name='Enroll Site A',
base=0,
#width=2 # Width value varies depending on number of samples in data
)
]
layout = go.Layout(
barmode='stack',
xaxis=dict(
showticklabels=True,
ticktext=dates_indexes,
tickvals=[i for i in indexes],
)
)
fig = dict(data = data, layout = layout)
iplot(fig, show_link=False)

Plotly: Plot multiple figures as subplots

These resources show how to take data from a single Pandas DataFrame and plot different columns subplots on a Plotly graph. I'm interested in creating figures from separate DataFrames and plotting them to the same graph as subplots. Is this possible with Plotly?
https://plot.ly/python/subplots/
https://plot.ly/pandas/subplots/
I'm creating each figure from a dataframe like this:
import pandas as pd
import cufflinks as cf
from plotly.offline import download_plotlyjs, plot,iplot
cf.go_offline()
fig1 = df.iplot(kind='bar',barmode='stack',x='Type',
y=mylist,asFigure=True)
Edit:
Here is an example based on Naren's feedback:
Create the dataframes:
a={'catagory':['loc1','loc2','loc3'],'dogs':[1,5,6],'cats':[3,1,4],'birds':[4,12,2]}
df1 = pd.DataFrame(a)
b={'catagory':['loc1','loc2','loc3'],'dogs':[12,3,5],'cats':[4,6,1],'birds':[7,0,8]}
df2 = pd.DataFrame(b)
The plot will just show the information for the dogs, not the birds or cats:
fig = tls.make_subplots(rows=2, cols=1)
fig1 = df1.iplot(kind='bar',barmode='stack',x='catagory',
y=['dogs','cats','birds'],asFigure=True)
fig.append_trace(fig1['data'][0], 1, 1)
fig2 = df2.iplot(kind='bar',barmode='stack',x='catagory',
y=['dogs','cats','birds'],asFigure=True)
fig.append_trace(fig2['data'][0], 2, 1)
iplot(fig)
Here's a short function in a working example to save a list of figures all to a single HTML file.
def figures_to_html(figs, filename="dashboard.html"):
with open(filename, 'w') as dashboard:
dashboard.write("<html><head></head><body>" + "\n")
for fig in figs:
inner_html = fig.to_html().split('<body>')[1].split('</body>')[0]
dashboard.write(inner_html)
dashboard.write("</body></html>" + "\n")
# Example figures
import plotly.express as px
gapminder = px.data.gapminder().query("country=='Canada'")
fig1 = px.line(gapminder, x="year", y="lifeExp", title='Life expectancy in Canada')
gapminder = px.data.gapminder().query("continent=='Oceania'")
fig2 = px.line(gapminder, x="year", y="lifeExp", color='country')
gapminder = px.data.gapminder().query("continent != 'Asia'")
fig3 = px.line(gapminder, x="year", y="lifeExp", color="continent",
line_group="country", hover_name="country")
figures_to_html([fig1, fig2, fig3])
You can get a dashboard that contains several charts with legends next to each one:
import plotly
import plotly.offline as py
import plotly.graph_objs as go
fichier_html_graphs=open("DASHBOARD.html",'w')
fichier_html_graphs.write("<html><head></head><body>"+"\n")
i=0
while 1:
if i<=40:
i=i+1
#______________________________--Plotly--______________________________________
color1 = '#00bfff'
color2 = '#ff4000'
trace1 = go.Bar(
x = ['2017-09-25','2017-09-26','2017-09-27','2017-09-28','2017-09-29','2017-09-30','2017-10-01'],
y = [25,100,20,7,38,170,200],
name='Debit',
marker=dict(
color=color1
)
)
trace2 = go.Scatter(
x=['2017-09-25','2017-09-26','2017-09-27','2017-09-28','2017-09-29','2017-09-30','2017-10-01'],
y = [3,50,20,7,38,60,100],
name='Taux',
yaxis='y2'
)
data = [trace1, trace2]
layout = go.Layout(
title= ('Chart Number: '+str(i)),
titlefont=dict(
family='Courier New, monospace',
size=15,
color='#7f7f7f'
),
paper_bgcolor='rgba(0,0,0,0)',
plot_bgcolor='rgba(0,0,0,0)',
yaxis=dict(
title='Bandwidth Mbit/s',
titlefont=dict(
color=color1
),
tickfont=dict(
color=color1
)
),
yaxis2=dict(
title='Ratio %',
overlaying='y',
side='right',
titlefont=dict(
color=color2
),
tickfont=dict(
color=color2
)
)
)
fig = go.Figure(data=data, layout=layout)
plotly.offline.plot(fig, filename='Chart_'+str(i)+'.html',auto_open=False)
fichier_html_graphs.write(" <object data=\""+'Chart_'+str(i)+'.html'+"\" width=\"650\" height=\"500\"></object>"+"\n")
else:
break
fichier_html_graphs.write("</body></html>")
print("CHECK YOUR DASHBOARD.html In the current directory")
Result:
You can also try the following using cufflinks:
cf.subplots([df1.figure(kind='bar',categories='category'),
df2.figure(kind='bar',categories='category')],shape=(2,1)).iplot()
And this should give you:
New Answer:
We need to loop through each of the animals and append a new trace to generate what you need. This will give the desired output I am hoping.
import pandas as pd
import numpy as np
import cufflinks as cf
import plotly.tools as tls
from plotly.offline import download_plotlyjs, plot,iplot
cf.go_offline()
import random
def generate_random_color():
r = lambda: random.randint(0,255)
return '#%02X%02X%02X' % (r(),r(),r())
a={'catagory':['loc1','loc2','loc3'],'dogs':[1,5,6],'cats':[3,1,4],'birds':[4,12,2]}
df1 = pd.DataFrame(a)
b={'catagory':['loc1','loc2','loc3'],'dogs':[12,3,5],'cats':[4,6,1],'birds':[7,0,8]}
df2 = pd.DataFrame(b)
#shared Xaxis parameter can make this graph look even better
fig = tls.make_subplots(rows=2, cols=1)
for animal in ['dogs','cats','birds']:
animal_color = generate_random_color()
fig1 = df1.iplot(kind='bar',barmode='stack',x='catagory',
y=animal,asFigure=True,showlegend=False, color = animal_color)
fig.append_trace(fig1['data'][0], 1, 1)
fig2 = df2.iplot(kind='bar',barmode='stack',x='catagory',
y=animal,asFigure=True, showlegend=False, color = animal_color)
#if we do not use the below line there will be two legend
fig2['data'][0]['showlegend'] = False
fig.append_trace(fig2['data'][0], 2, 1)
#additional bonus
#use the below command to use the bar chart three mode
# [stack, overlay, group]
#as shown below
#fig['layout']['barmode'] = 'overlay'
iplot(fig)
Output:
Old Answer:
This will be the solution
Explanation:
Plotly tools has a subplot function to create subplots you should read the documentation for more details here. So I first use cufflinks to create a figure of the bar chart. One thing to note is cufflinks create and object with both data and layout. Plotly will only take one layout parameter as input, hence I take only the data parameter from the cufflinks figure and append_trace it to the make_suplots object. so fig.append_trace() the second parameter is row number and third parameter is column number
import pandas as pd
import cufflinks as cf
import numpy as np
import plotly.tools as tls
from plotly.offline import download_plotlyjs, plot,iplot
cf.go_offline()
fig = tls.make_subplots(rows=2, cols=1)
df = pd.DataFrame(np.random.randint(0,100,size=(100, 4)), columns=list('ABCD'))
fig1 = df.iplot(kind='bar',barmode='stack',x='A',
y='B',asFigure=True)
fig.append_trace(fig1['data'][0], 1, 1)
df2 = pd.DataFrame(np.random.randint(0,100,size=(100, 4)), columns=list('EFGH'))
fig2 = df2.iplot(kind='bar',barmode='stack',x='E',
y='F',asFigure=True)
fig.append_trace(fig2['data'][0], 2, 1)
iplot(fig)
If you want to add a common layout to the subplot I suggest that you do
fig.append_trace(fig2['data'][0], 2, 1)
fig['layout']['showlegend'] = False
iplot(fig)
or even
fig.append_trace(fig2['data'][0], 2, 1)
fig['layout'].update(fig1['layout'])
iplot(fig)
So in the first example before plotting, I access the individual parameters of the layout object and change them, you need to go through layout object properties for refernce.
In the second example before plotting, I update the layout of the figure with the cufflinks generated layout this will produce the same output as we see in cufflinks.
You've already received a few suggestions that work perfectly well. They do however require a lot of coding. Facet / trellis plots using px.bar() will let you produce the plot below using (almost) only this:
px.bar(df, x="category", y="dogs", facet_row="Source")
The only extra steps you'll have to take is to introduce a variable on which to split your data, and then gather or concatenate your dataframes like this:
df1['Source'] = 1
df2['Source'] = 2
df = pd.concat([df1, df2])
And if you'd like to include the other variables as well, just do:
fig = px.bar(df, x="category", y=["dogs", "cats", "birds"], facet_row="Source")
fig.update_layout(barmode = 'group')
Complete code:
# imports
import plotly.express as px
import pandas as pd
# data building
a={'category':['loc1','loc2','loc3'],'dogs':[1,5,6],'cats':[3,1,4],'birds':[4,12,2]}
df1 = pd.DataFrame(a)
b={'category':['loc1','loc2','loc3'],'dogs':[12,3,5],'cats':[4,6,1],'birds':[7,0,8]}
df2 = pd.DataFrame(b)
# data processing
df1['Source'] = 1
df2['Source'] = 2
df = pd.concat([df1, df2])
# plotly figure
fig = px.bar(df, x="category", y="dogs", facet_row="Source")
fig.show()
#fig = px.bar(df, x="category", y=["dogs", "cats", "birds"], facet_row="Source")
#fig.update_layout(barmode = 'group')

Categories

Resources