I want use a for cycle to call a charting function and then represent the outcome chart into a section of a multi charting pageExample single chart
expected outcome
I have a charting function (see below Charting Function Section) that i recall in a the main script with a for cycle to get several charts in sequence. Now I would like to represent all the charts, in compact size (2 columns 4 rows) in one single page. In literature I find that Subplot allows me to do so but I struggle to find the right command to represent the outcome from the charting function.
I thought something like the below in the Main Section would work but it is not
---------- Main Section ---------
import pandas as pd
import numpy as np
import plotly.graph_objs as go
from sklearn.cluster import KMeans
from plotly.subplots import make_subplots
for cont in range(8):
fig = charting_func(cont)
fig_all.add_trace(fig,
row=1, col=1
) #row and col incrementing function to be defined
fig_all.update_layout(height=600, width=800, title_text="Side By Side Subplots")
fig_all.show()
----- Charting Function ------
def charting_func(n_chrt):
# Arbitrarily 10 colors for up to 10 clusters
#colors = ['red', 'orange', 'yellow', 'green', 'blue', 'indigo', 'violet', 'purple','pink', 'silver']
# Create Scatter plot, assigning each point a color where
# point group = color index.
fig = btc.plot.scatter(
x=btc.index,
y="Adj Close",
color=[colors[i] for i in lists_clusters[n_chrt]],
title="k-values = {0}".format(n_chrt+2)
)
# Add horizontal lines
for cluster_avg in output[n_chrt][1:-1]:
fig.add_hline(y=cluster_avg, line_width=1, line_color="blue")
# Add a trace of the price for better clarity
fig.add_trace(go.Scatter(
x=btc.index,
y=btc['Adj Close'],
line_color="black",
line_width=1
))
# Make it pretty
layout = go.Layout(
plot_bgcolor='#D9D9D9',
showlegend=False,
# Font Families
font_family='Monospace',
font_color='#000000',
font_size=20,
xaxis=dict(
rangeslider=dict(
visible=False
))
)
fig.update_layout(layout)
return fig
type here
The basic form of a subplot is to add a location arrangement to the graph setup. So the functionalization needs to have matrix information or something like that. I have no data to present, so I have taken the stock prices of 4 companies and graphed them. As for the clustering by price, it is not included in the code, so the binning process is used to get the values and labels for the horizontal line. Please rewrite this part to your own logic. If you are good enough, the functionalization should work well.
import pandas as pd
import plotly.graph_objects as go
from plotly.subplots import make_subplots
import itertools
import yfinance as yf
stock = ['TSLA','MSFT','AAPL','AMD']
#fig = go.Figure()
fig = make_subplots(rows=2, cols=2, subplot_titles=['MSFT','TSLA','AMD','AAPL'])
for s,rc in zip(stock, itertools.product([1,2],[2,1])):
#print(s, rc[0], rc[1])
df = yf.download(s, start="2017-09-01", end="2022-04-01", interval='1mo', progress=False)
colors = ['blue', 'red', 'green', 'purple', 'orange']
s_cut, bins = pd.cut(df['Adj Close'], 5, retbins=True, labels=colors)
fig.add_trace(go.Scatter(mode='markers+lines',
x=df.index,
y=df['Adj Close'],
marker=dict(
size=10,
color=s_cut.tolist()
)),
row=rc[0], col=rc[1]
)
for b in bins[1:-1]:
fig.add_hline(y=b, line_width=1, line_color="blue", row=rc[0], col=rc[1])
fig.update_layout(autosize=True, height=600, title_text="Side By Side Subplots")
fig.show()
Related
Here is CDF visualization I have:
fig_cdf = px.ecdf(df['Timespan'], color_discrete_sequence=['blue'],ecdfnorm='probability', orientation='h')
fig_cdf.add_hline(y=90, line_width=2, line_color="red", name='90%', visible=True)
fig_cdf.add_hline(y=30, line_width=2, line_color="red", name='75%', visible=True)
fig_cdf.update_layout(width=500, height=500)
The problem here is that i want horizontal lines' names to be visible and appear as 2nd and 3rd legends. For this, I tried to add visible=True. However, it seems not to work. What's wrong?
This is one way of doing it...
Add the two lines to the dataframe as new columns
Use color_discrete_sequence to identify the colors you want
I am using some random dummy data, which you can replace with your data
import plotly.express as px
df = pd.DataFrame({'firstline': random.sample(range(1, 500), 20),'myX' : range(20)}) #My dummy data
#Add the two lines to dataframe
df['90%'] = [90] * 20
df['75%'] = [75] * 20
fig = px.line(df,
y = ['firstline', '90%', '75%'], x= 'myX', color_discrete_sequence=["blue", "red", "red"])
fig.update_layout(legend_title_text='Legend Heading') #Update Legend header if you dont like 'variable'
fig.show()
Output graph
This is my first experience with this graph, but to add it to the legend, you can use the line mode of the scatter plot. So I took the maximum x-axis value used in the first graph and set the legend name Average using the appropriate y-axis value. This example is taken from the official reference.
import plotly.express as px
import plotly.graph_objects as go
df = px.data.tips()
fig = px.ecdf(df, x=["total_bill", "tip"])
xmax = max(fig.data[0]['x'])
#print(xmax)
fig.add_trace(go.Scatter(
x=[0,xmax],
y=[0.6,0.6],
mode='lines',
line_color='red',
name='mean',
showlegend=True
))
fig.show()
I'm using a multi-index data frame to plot a line chart. I can see the correct result when I plot the graph using Matplotlib but the data frame shows the wrong output when plotted using Plotly scatter charts- why?
import pandas as pd
data = pd.DataFrame([
('Q1','Blue',100),
('Q1','Green',300),
('Q2','Blue',200),
('Q2','Green',350),
('Q3','Blue',300),
('Q3','Green',400),
('Q4','Blue',400),
('Q4','Green',450),
],
columns=['quarter', 'company', 'value']
)
data = data.set_index(['quarter', 'company']).value
data.unstack().plot(kind='bar', stacked=True)
The above code plots the right chart. The below code also generate the right result.
fig = go.Figure()
fig.add_trace(go.Scatter(x=sample.index, y=sample['Blue'],
#mode='lines+markers', name='',
#line=dict(color=colors_list[1],width=2,) ,
)
)
but I don't know how to plot both Blue and Green in the scatter plot at the same time?
example:
fig = go.Figure()
fig.add_trace(go.Scatter(x=sample.index, y=sample,
#mode='lines+markers', name='',
#line=dict(color=colors_list[1],width=2,) ,
)
)
Can anyone help how to plot both Blue and Green together?
Your question is a bit unclear, but I'm assuming that your primary objective here is to display values accross an array of quarters where values are split in two groups ['blue', 'red']. (I can't quite understand why you're asking for a plotly scatter figure but showing a matplotlib bar chart...). Anyway, If I'm right, then your use case is very well suited for plotly.express, specifically px.scatter with which the following snippet will produce the figure below.
import pandas as pd
import plotly.graph_objects as go
import plotly.express as px
data = pd.DataFrame([
('Q1','Blue',100),
('Q1','Green',300),
('Q2','Blue',200),
('Q2','Green',350),
('Q3','Blue',300),
('Q3','Green',400),
('Q4','Blue',400),
('Q4','Green',450),
],
columns=['quarter', 'company', 'value']
)
fig = px.scatter(data, x = 'quarter', y = 'value',
color = 'company',
color_discrete_sequence=['Blue', 'Green'])
fig.show()
As vestland pointed in his good answer you can use Plotly Express to do it simply.
However, if you do not want to use Plotly Express, you have to add plots (traces) to the figure and configure the figure keys as below.
import plotly.graph_objects as go
fig = go.Figure()
fig.add_trace(go.Scatter(x=sample.index, y=sample['Green'], mode='markers', name = 'Green', marker_color = 'Green'))
fig.add_trace(go.Scatter(x=sample.index, y=sample['Blue'], mode='markers', name = 'Blue', marker_color = 'Blue'))
fig.update_layout(title="The Title", xaxis_title="Quarter", yaxis_title="Value", legend_title="Company")
gives
image of plotly chart
Hello, I'm really struggling to figure out how to format the axes on this chart. I've gone through the documentation and tried all sorts of different formatting suggestions from here and elsewhere but really not getting it. As you can see, the bottom chart has a .5 number, I want that to be skipped altogether and only have whole numbers along the axis.
I've seen ,d as a tickformat option to do this in about every answer, but I can't get that to work or I'm not seeing how to apply it to the second chart.
Can anyone with some Plotly charting experience help me out?
Here's the pertinent code:
def create_chart():
#Put data together into an interactive chart
fig.update_layout(height=500, width=800, yaxis_tickprefix = '$', hovermode='x unified', xaxis_tickformat =',d',
template=symbol_template, separators=".", title_text=(df.columns[DATA_COL_1]) + " & Units 2015-2019"
)
I believe what is happening is that the xaxis_tickformat parameter is affecting only the first subplot, but not the second one. To modify the formatting for each subplot, you can pass a dictionary with the tickformat parameter to yaxis, yaxis2, .... and so on for however many subplots you have (in your case, you only have 2 subplots).
import pandas as pd
from plotly.subplots import make_subplots
import plotly.graph_objects as go
## recreate the df
df = pd.DataFrame({'Year':[2015,2016,2017,2018,2019],
'Sales':[8.8*10**7,8.2*10**7,8.5*10**7,9.1*10**7,9.6*10**7],
'Units':[36200,36500,36900,37300,37700]})
def create_chart():
#Put data together into an interactive chart
fig = make_subplots(rows=2, cols=1)
fig.add_trace(go.Scatter(
x=df.Year,
y=df.Sales,
name='Sales',
mode='lines+markers'
), row=1, col=1)
fig.add_trace(go.Scatter(
x=df.Year,
y=df.Units,
name='Units',
mode='lines+markers'
), row=2, col=1)
fig.update_layout(
title_x=0.5,
height=500,
width=800,
yaxis_tickprefix = '$',
hovermode='x unified',
xaxis_tickformat =',d',
## this will change the formatting for BOTH subplots
yaxis=dict(tickformat ='d'),
yaxis2=dict(tickformat ='d'),
# template=symbol_template,
separators=".",
title={
'text':"MCD Sales & Units 2015-2019",
'x':0.5
}
)
fig.show()
create_chart()
I have plotted a figure with 2 subplots, each with different scales. Everything plots correctly, except the colorscales are both plotted on the right and completely overlap - they are are not readable. I cannot find out how to position/reposition the individual subplot scales. I have included my code below. Thanks.
import pandas as pd
import plotly.graph_objects as go
from plotly.subplots import make_subplots
df = pd.read_csv(entry)
custColorscale = [[0, 'green'], [0.5, 'red'], [1, 'rgb(50, 50, 50)']]
fig = make_subplots(
rows=1, cols=2, subplot_titles=('one', 'two'))
fig.add_trace(
go.Scatter(x=df['tO'],
y=df['t1'],
mode='markers',
marker=dict(colorscale=custColorscale,
cmin=0, cmax=2,
size=6, color=df['Var1'],
showscale=True),
text=df['Var2']),
1, 1)
fig.add_trace(
go.Scatter(x=df['tO'],
y=df['t1'],
mode='markers',
marker=dict(
size=6, color=df['Var2'],
showscale=True),
text=df['Var2']),
1, 2)
fig.update_layout(height=700, width=1900,
title='Raw data')
fig.update_layout(coloraxis=dict(
colorscale='Bluered_r'))
fig.write_html(fig, file='raw plots.html', auto_open=True)
Looking through the Plotly documentation you find this which provide some hints as to how to solve the problem. Scroll to the 'marker' attributes and you will find that it has sub-attribute called 'colorbar'. The colorbar in turn has multiple options that could help set the plot the way you want. Particularly you find the 'x', 'y' and 'len' attributes of the colorbar very useful. You can use them to position the scales.
This question is also related to this but for a contour plot - you are making a scatterplot which is why the scatterplot reference would be what one should search.
A minimal working example (MWE) is shown below but with a toy dataset.
## make necessary imports
import numpy as np
from plotly.subplots import make_subplots
import plotly.graph_objects as go
import pandas as pd
## make a fake dataset with pandas
d = {'t0': [i for i in np.arange(0.,10.,1.)], 't1': [i for i in
np.arange(10.,20.,1.)],'Var1': [i for i in np.arange(20.,30.,1.)],'Var2':
[i for i in np.arange(30.,40.,1.)] }
df = pd.DataFrame(data=d) #the dataset is made to mock the example code you provided
And for your plot you have the following :
# make subplots
custColorscale = [[0, 'green'], [0.5, 'red'], [1, 'rgb(50, 50, 50)']]
fig = make_subplots(
rows=1, cols=2, subplot_titles=('one', 'two'),horizontal_spacing = 0.4)
# plot 1
fig.add_trace(
go.Scatter(x=df['t0'],
y=df['t1'],
mode='markers',
marker=dict(colorscale=custColorscale,
cmin=0, cmax=2,
size=6, color=df['Var1'],
showscale=True,colorbar=dict(len=1.05, x=0.35
,y=0.49)), text=df['Var2']), 1, 1)
## plot 2
fig.add_trace(
go.Scatter(x=df['t0'],
y=df['t1'],
mode='markers',
marker=dict(
size=6, color=df['Var2'],
showscale=True,colorbar=dict(len=1.05, x=1.2 , y=0.49)),
text=df['Var2']),
1, 2 )
# show plots
fig.update_layout(height=500, width=700,
title='Raw data')
fig.update_layout(coloraxis=dict(
colorscale='Bluered_r'))
fig.show()
The only additions were:
The colorbar attribute of the marker.
The horizontal spacing to allow space for the first scale.
Feel free to play with these attributes.
I hope this helps!
Best regards.
I am wondering what is best practice to create subplots using Python Plotly. Is it to use plotly.express or the standard plotly.graph_objects?
I'm trying to create a figure with two subplots, which are stacked bar charts. The following code doesn't work. I didn't find anything useful in the official documentation. The classic Titanic dataset was imported as train_df here.
import plotly.express as px
train_df['Survived'] = train_df['Survived'].astype('category')
fig1 = px.bar(train_df, x="Pclass", y="Age", color='Survived')
fig2 = px.bar(train_df, x="Sex", y="Age", color='Survived')
trace1 = fig1['data'][0]
trace2 = fig2['data'][0]
fig = make_subplots(rows=1, cols=2, shared_xaxes=False)
fig.add_trace(trace1, row=1, col=1)
fig.add_trace(trace2, row=1, col=2)
fig.show()
I got the following figure:
What I expect is as follows:
I'm hoping that the existing answer suits your needs, but I'd just like to note that the statement
it's not possible to subplot stakedbar (because stacked bar are in facted figures and not traces
is not entirely correct. It's possible to build a plotly subplot figure using stacked bar charts as long as you put it together correctly using add_trace() and go.Bar(). And this also answers your question regarding:
I am wondering what is best practice to create subplots using Python Plotly. Is it to use plotly.express or the standard plotly.graph_objects?
Use plotly.express ff you find a px approach that suits your needs. And like in your case where you do not find it; build your own subplots using plotly.graphobjects.
Below is an example that will show you one such possible approach using the titanic dataset. Note that the column names are noe the same as yours since there are no capital letters. The essence of this approav is that you use go.Bar() for each trace, and specify where to put those traces using the row and col arguments in go.Bar(). If you assign multiple traces to the same row and col, you will get stacked bar chart subplots if you specify barmode='stack' in fig.update_layout(). Usingpx.colors.qualitative.Plotly[i]` will let you assign colors from the standard plotly color cycle sequentially.
Plot:
Code:
from plotly.subplots import make_subplots
import plotly.graph_objects as go
import plotly.express as px
import pandas as pd
url = "https://raw.github.com/mattdelhey/kaggle-titanic/master/Data/train.csv"
titanic = pd.read_csv(url)
#titanic.info()
train_df=titanic
train_df
# data for fig 1
df1=titanic.groupby(['sex', 'pclass'])['survived'].aggregate('mean').unstack()
# plotly setup for fig
fig = make_subplots(2,1)
fig.add_trace(go.Bar(x=df1.columns.astype('category'), y=df1.loc['female'],
name='female',
marker_color = px.colors.qualitative.Plotly[0]),
row=1, col=1)
fig.add_trace(go.Bar(x=df1.columns.astype('category'), y=df1.loc['male'],
name='male',
marker_color = px.colors.qualitative.Plotly[1]),
row=1, col=1)
# data for plot 2
age = pd.cut(titanic['age'], [0, 18, 80])
df2 = titanic.pivot_table('survived', [age], 'pclass')
groups=['(0, 18]', '(18, 80]']
fig.add_trace(go.Bar(x=df2.columns, y=df2.iloc[0],
name=groups[0],
marker_color = px.colors.qualitative.Plotly[3]),
row=2, col=1)
fig.add_trace(go.Bar(x=df2.columns, y=df2.iloc[1],
name=groups[1],
marker_color = px.colors.qualitative.Plotly[4]),
row=2, col=1)
fig.update_layout(title=dict(text='Titanic survivors by sex and age group'), barmode='stack', xaxis = dict(tickvals= df1.columns))
fig.show()
fig.show()
From what I know, it's not possible to subplot stakedbar (because stacked bar are in facted figures and not traces)...
On behalf of fig.show(), you can put to check if the html file is okay for you (The plots are unfortunately one under the other...) :
with open('p_graph.html', 'a') as f:
f.write(fig1.to_html(full_html=False, include_plotlyjs='cdn',default_height=500))
f.write(fig2.to_html(full_html=False, include_plotlyjs='cdn',default_height=500))
try the code below to check if the html file generate can be okay for you:
import pandas as pd
import plotly.graph_objects as go
#Remove the .astype('category') to easily
#train_df['Survived'] = train_df['Survived'].astype('category')
Pclass_pivot=pd.pivot_table(train_df,values='Age',index='Pclass',
columns='Survived',aggfunc=lambda x: len(x))
Sex_pivot=pd.pivot_table(train_df,values='Age',index='Sex',
columns='Survived',aggfunc=lambda x: len(x))
fig1 = go.Figure(data=[
go.Bar(name='Survived', x=Pclass_pivot.index.values, y=Pclass_pivot[1]),
go.Bar(name='NotSurvived', x=Pclass_pivot.index.values, y=Pclass_pivot[0])])
# Change the bar mode
fig1.update_layout(barmode='stack')
fig2 = go.Figure(data=[
go.Bar(name='Survived', x=Sex_pivot.index.values, y=Sex_pivot[1]),
go.Bar(name='NotSurvived', x=Sex_pivot.index.values, y=Sex_pivot[0])])
# Change the bar mode
fig2.update_layout(barmode='stack')
with open('p_graph.html', 'a') as f:
f.write(fig1.to_html(full_html=False, include_plotlyjs='cdn',default_height=500))
f.write(fig2.to_html(full_html=False, include_plotlyjs='cdn',default_height=500))
I managed to generate the subplots using the add_bar function.
Code:
from plotly.subplots import make_subplots
# plotly can only support one legend per graph at the moment.
fig = make_subplots(
rows=1, cols=2,
subplot_titles=("Pclass vs. Survived", "Sex vs. Survived")
)
fig.add_bar(
x=train_df[train_df.Survived == 0].Pclass.value_counts().index,
y=train_df[train_df.Survived == 0].Pclass.value_counts().values,
text=train_df[train_df.Survived == 0].Pclass.value_counts().values,
textposition='auto',
name='Survived = 0',
row=1, col=1
)
fig.add_bar(
x=train_df[train_df.Survived == 1].Pclass.value_counts().index,
y=train_df[train_df.Survived == 1].Pclass.value_counts().values,
text=train_df[train_df.Survived == 1].Pclass.value_counts().values,
textposition='auto',
name='Survived = 1',
row=1, col=1
)
fig.add_bar(
x=train_df[train_df.Survived == 0].Sex.value_counts().index,
y=train_df[train_df.Survived == 0].Sex.value_counts().values,
text=train_df[train_df.Survived == 0].Sex.value_counts().values,
textposition='auto',
marker_color='#636EFA',
showlegend=False,
row=1, col=2
)
fig.add_bar(
x=train_df[train_df.Survived == 1].Sex.value_counts().index,
y=train_df[train_df.Survived == 1].Sex.value_counts().values,
text=train_df[train_df.Survived == 1].Sex.value_counts().values,
textposition='auto',
marker_color='#EF553B',
showlegend=False,
row=1, col=2
)
fig.update_layout(
barmode='stack',
height=400, width=1200,
)
fig.update_xaxes(ticks="inside")
fig.update_yaxes(ticks="inside", col=1)
fig.show()
Resulting plot:
Hope this is helpful to the newbies of plotly like me.