I have a plotly scatter plot like this example:
x = [1,2,3,4,5]
y = [3,2,3,5,6]
fig = go.Figure()
fig.add_trace(go.Scatter(x=x, y=y))
fig.show()
Now I want to label the x-axis numbers as dates with this dates for example:
dates = pd.date_range('2022-01-01', periods=len(x), freq='1H')
dates.values
array(['2022-01-01T00:00:00.000000000',
'2022-01-01T01:00:00.000000000',
'2022-01-01T02:00:00.000000000', '2022-01-01T03:00:00.000000000',
'2022-01-01T04:00:00.000000000'], dtype='datetime64[ns]')
How can i do this?
The Background here is that I want to add vlines or other things based on the numerical x axis I only want to show the labels as dates. Is this possible? Is the title of the question understandable?
To change the tick to a date while keeping the x-axis already created alive, it is easiest to specify an x-value for the tick value and convert the tick string from a date to a string.
import plotly.graph_objects as go
import pandas as pd
x = [1,2,3,4,5]
y = [3,2,3,5,6]
dates = pd.date_range('2022-01-01', periods=len(x), freq='1H')
fig = go.Figure()
fig.add_trace(go.Scatter(x=x, y=y))
fig.update_xaxes(tickvals=x, ticktext=[d.strftime('%Y-%m-%d %H:00') for d in dates])
fig.show()
I'm creating a dashboard in which I would like to compare the difference of price between two regions directly. If the price of region 1 is higher, y is POSITIVE, if the price of region 2 is higher, y is NEGATIVE.
The problem is that I would like the line and its fill to change color accordingly to its value, so it has a better representation.
I'm using fill='tozeroy'. I would like y-negative = red and y-positive = blue, for the lines and the fill.
def func(est1, est2):
est1, est2 = 'RIO GRANDE DO SUL', 'SANTA CATARINA' # filter to simulate the callback
df1 = df[df.ESTADO.isin([est1])]
df2 = df[df.ESTADO.isin([est2])]
df_final = pd.DataFrame()
df_estado1 = df1.groupby(pd.PeriodIndex(df1['DATA'], freq="M"))['VALOR REVENDA (R$/L)'].mean().reset_index()
df_estado2 = df2.groupby(pd.PeriodIndex(df2['DATA'], freq="M"))['VALOR REVENDA (R$/L)'].mean().reset_index()
df_estado1['DATA'] = pd.PeriodIndex(df_estado1['DATA'], freq="M")
df_estado2['DATA'] = pd.PeriodIndex(df_estado2['DATA'], freq="M")
df_final['DATA'] = df_estado1['DATA'].astype('datetime64[ns]')
df_final['VALOR REVENDA (R$/L)'] = df_estado1['VALOR REVENDA (R$/L)']-df_estado2['VALOR REVENDA (R$/L)']
fig = go.Figure()
fig.add_trace(go.Scatter(name='Comparação', y=df_final['VALOR REVENDA (R$/L)'], x=df_final['DATA'],
fill='tozeroy', mode='lines'))
return fig
Just for help porpouses, that's the "df_final" format which is returned:
df_final DataFrame
Here's the graph that is being returned from the function: graph returned
Also, how can I style my fill? Maybe add some gradient etc
I found this Plotly reference library, where I scraped the information I'm answering you with: https://plotly.com/python/creating-and-updating-figures/#plotly-express
import plotly.express as px
df = px.data.iris()
fig = px.scatter(df, x="sepal_width", y="sepal_length", color="species",
title="Using The add_trace() method With A Plotly Express Figure")
fig.add_trace(
go.Scatter(
x=[2, 4],
y=[4, 8],
mode="lines",
line=go.scatter.Line(color="gray"),
showlegend=False)
)
fig.show()
Basically, if you put "df_final" in the place of df, and change the axis's data, you'll be good to go.
I am trying to write a for loop that for distplot subplots.
I have a dataframe with many columns of different lengths. (not including the NaN values)
fig = make_subplots(
rows=len(assets), cols=1,
y_title = 'Hourly Price Distribution')
i=1
for col in df_all.columns:
fig = ff.create_distplot([[df_all[[col]].dropna()]], col)
fig.append()
i+=1
fig.show()
I am trying to run a for loop for subplots for distplots and get the following error:
PlotlyError: Oops! Your data lists or ndarrays should be the same length.
UPDATE:
This is an example below:
df = pd.DataFrame({'2012': np.random.randn(20),
'2013': np.random.randn(20)+1})
df['2012'].iloc[0] = np.nan
fig = ff.create_distplot([df[c].dropna() for c in df.columns],
df.columns,show_hist=False,show_rug=False)
fig.show()
I would like to plot each distribution in a different subplot.
Thank you.
Update: Distribution plots
Calculating the correct values is probably both quicker and more elegant using numpy. But I often build parts of my graphs using one plotly approach(figure factory, plotly express) and then use them with other elements of the plotly library (plotly.graph_objects) to get what I want. The complete snippet below shows you how to do just that in order to build a go based subplot with elements from ff.create_distplot. I'd be happy to give further explanations if the following suggestion suits your needs.
Plot
Complete code
import numpy as np
import pandas as pd
import plotly.express as px
import plotly.figure_factory as ff
from plotly.subplots import make_subplots
import plotly.graph_objects as go
df = pd.DataFrame({'2012': np.random.randn(20),
'2013': np.random.randn(20)+1})
df['2012'].iloc[0] = np.nan
df = df.reset_index()
dfm = pd.melt(df, id_vars=['index'], value_vars=df.columns[1:])
dfm = dfm.dropna()
dfm.rename(columns={'variable':'year'}, inplace = True)
cols = dfm.year.unique()
nrows = len(cols)
fig = make_subplots(rows=nrows, cols=1)
for r, col in enumerate(cols, 1):
dfs = dfm[dfm['year']==col]
fx1 = ff.create_distplot([dfs['value'].values], ['distplot'],curve_type='kde')
fig.add_trace(go.Scatter(
x= fx1.data[1]['x'],
y =fx1.data[1]['y'],
), row = r, col = 1)
fig.show()
First suggestion
You should:
1. Restructure your data with pd.melt(df, id_vars=['index'], value_vars=df.columns[1:]),
2. and the use the occuring column 'variable' to build subplots for each year through the facet_row argument to get this:
In the complete snippet below you'll see that I've changed 'variable' to 'year' in order to make the plot more intuitive. There's one particularly convenient side-effect with this approach, namely that running dfm.dropna() will remove the na value for 2012 only. If you were to do the same thing on your original dataframe, the corresponding value in the same row for 2013 would also be removed.
import numpy as np
import pandas as pd
import plotly.express as px
df = pd.DataFrame({'2012': np.random.randn(20),
'2013': np.random.randn(20)+1})
df['2012'].iloc[0] = np.nan
df = df.reset_index()
dfm = pd.melt(df, id_vars=['index'], value_vars=df.columns[1:])
dfm = dfm.dropna()
dfm.rename(columns={'variable':'year'}, inplace = True)
fig = px.histogram(dfm, x="value",
facet_row = 'year')
fig.show()
i am looking for a solution to plot a dataframe with a datetimeindex as a "carpet plot". i prefer plotly, but I also would use other libs. maybe "carpet plot" is not the correct name for the plot?!
i expect the index as xaxis label and for every column a "bucket". maybe a stacked area plot is a solution. i am not able to figure it out.
import pandas as pd
import numpy as np
from datetime import datetime, timedelta
date_today = datetime.now()
days = pd.date_range(date_today, date_today + timedelta(7), freq='D')
np.random.seed(seed=1111)
data = [1,1,1,0,1,1,0,1]
data1 = [1,1,1,0,0,1,0,1]
data2 = [1,0,1,0,1,1,0,1]
df = pd.DataFrame({'test': days, 'col1': data, 'col2': data1, 'col3': data2})
df = df.set_index('test')
as example:
You can simply use imshow from plotly:
# using your data sample:
fig = px.imshow(df)
fig.show()
this gives you:
With a little bit more styling:
fig = px.imshow(df, width=300, height=500,
labels=dict(x="Columns", y="Days"),
x=df.columns,
y=df.index,
)
fig.show()
you can get:
Or horizontal layout, with no coloraxis and another colorscale (Viridis), if you like his better. For further details see the API reference
fig = px.imshow(df.T, width=500, height=300,
labels=dict(x="Columns", y="Days"),
x=df.T.columns,
y=df.T.index,
color_continuous_scale = 'Viridis',
)
fig.update_layout(coloraxis_showscale=False)
fig.show()
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')