Placement of Y labels plotly python horizontal barchart - python

I'm looking for a way to get the y labels of a plotly horizontal barchart above the grouped bars. What i'm looking for is:
import pandas as pd
import plotly.graph_objects as go
test_df = pd.DataFrame({'component':['BAR 1','BAR 2','BAR 3'],'mean':[7.4,7.8,6.5],'mean_proj':[6.8,7.9,8.4]})
def barchart2(df,x1,x2,y):
fig = go.Figure()
fig.add_trace(go.Bar(name=x1,x=df[x1],y=df[y],orientation='h',hoverinfo=None,marker_color='#221435')),
fig.add_trace(go.Bar(name=x2,x=df[x2],y=df[y],orientation='h',hoverinfo=None,marker_color='rgb(55,177,140)')),
fig.update_xaxes(showgrid=False, zeroline=False)
fig.update_yaxes(showgrid=False, zeroline=False)
fig.update_layout(paper_bgcolor='rgba(0,0,0,0)',plot_bgcolor='rgba(0,0,0,0)',bargap=0.20,margin=dict(t=30,b=5,l=25,r=0))
fig.update_layout(barmode='group')
return fig.write_html('test.html',auto_open=True)
barchart2(test_df,'mean','mean_proj','component')

An approach to simulating this is to duplicate traces and use text parameters on these traces
import pandas as pd
import plotly.graph_objects as go
test_df = pd.DataFrame({'component':['BAR 1','BAR 2','BAR 3'],'mean':[7.4,7.8,6.5],'mean_proj':[6.8,7.9,8.4]})
def barchart2(df,x1,x2,y):
fig = go.Figure()
fig.add_trace(go.Bar(name=x1,x=df[x1],y=df[y],marker_color='#221435')),
fig.add_trace(go.Bar(name=x1,x=df[x1],y=df[y],marker_color='rgba(0,0,0,0)', text=x1, showlegend=False)),
fig.add_trace(go.Bar(name=x2,x=df[x2],y=df[y],marker_color='rgb(55,177,140)')),
fig.add_trace(go.Bar(name=x2,x=df[x2],y=df[y],marker_color='rgba(0,0,0,0)', text=x2, showlegend=False)),
fig.update_traces(orientation="h", hoverinfo=None, insidetextanchor="start")
fig.update_xaxes(showgrid=False, zeroline=False)
fig.update_yaxes(showgrid=False, zeroline=False)
fig.update_layout(paper_bgcolor='rgba(0,0,0,0)',plot_bgcolor='rgba(0,0,0,0)',bargap=0.20,margin=dict(t=30,b=5,l=25,r=0))
fig.update_layout(barmode='group')
# return fig.write_html('test.html',auto_open=True)
return fig
barchart2(test_df,'mean','mean_proj','component')
where y-axis ticks are labels
Same technique.
import pandas as pd
import plotly.graph_objects as go
test_df = pd.DataFrame({'component':['BAR 1','BAR 2','BAR 3'],'mean':[7.4,7.8,6.5],'mean_proj':[6.8,7.9,8.4]})
def barchart2(df,x1,x2,y):
fig = go.Figure()
fig.add_trace(go.Bar(name=x1,x=df[x1],y=df[y],marker_color='#221435')),
fig.add_trace(go.Bar(name=x1,x=df[x1],y=df[y],marker_color='rgba(0,0,0,0)', text=df[y], showlegend=False)),
fig.add_trace(go.Bar(name=x2,x=df[x2],y=df[y],marker_color='rgb(55,177,140)')),
fig.add_trace(go.Bar(name=x2,x=df[x2],y=df[y],marker_color='rgba(0,0,0,0)', text=df[y], showlegend=False)),
fig.update_traces(orientation="h", hoverinfo=None, insidetextanchor="start")
fig.update_xaxes(showgrid=False, zeroline=False)
fig.update_yaxes(showgrid=False, zeroline=False)
fig.update_layout(paper_bgcolor='rgba(0,0,0,0)',plot_bgcolor='rgba(0,0,0,0)',bargap=0.20,margin=dict(t=30,b=5,l=25,r=0))
fig.update_layout(barmode='group')
# return fig.write_html('test.html',auto_open=True)
return fig.update_yaxes(visible=False)
barchart2(test_df,'mean','mean_proj','component')

For anyone who's looking for another way to fix this (without the use of hidden traces) you could also use fig.add_annotations. With add_annotations you can add text on certain places in the graph.
import pandas as pd
import plotly.graph_objects as go
test_df = pd.DataFrame({'component':['BAR 1','BAR 2','BAR 3','BAR 4','BAR 5','BAR 6','BAR 7'],'mean':[7.4,7.8,6.5,7.7,7.4,7.8,6.5],'mean_proj':[6.8,7.9,8.4,6.3,7.9,8.4,6.3]})
def barchart2(df,x1,x2,y,font):
fig = go.Figure()
fig.add_trace(go.Bar(name=x1,x=df[x1],y=df[y],orientation='h',hoverinfo=None,marker_color='#221435')),
fig.add_trace(go.Bar(name=x2,x=df[x2],y=df[y],orientation='h',hoverinfo=None,marker_color='rgb(55,177,140)')),
fig.update_xaxes(showgrid=False, zeroline=False,showticklabels=False)
fig.update_yaxes(showgrid=False, zeroline=False,showticklabels=False)
fig.update_layout(paper_bgcolor='rgba(0,0,0,0)',plot_bgcolor='rgba(0,0,0,0)',bargap=0.50,
margin=dict(t=30,b=5,l=0,r=0),barmode='group',
legend=dict(yanchor='bottom',y=-0.1,xanchor='left',x=0,font=dict(family=font,size=25)))
startplace = 6.4
for i in df[y].unique():
fig.add_annotation(x=0.23,y=startplace,
text=i,
showarrow=False,
font=dict(family=font,color='#EB0045',size=25)),
startplace = startplace - 1
return fig.write_html('fig1.html',auto_open=True)
barchart2(test_df,'mean','mean_proj','component','Arial')
The code will result in the following graph:

Related

How to highlight a single data point on a scatter plot using plotly express

In a scatter plot created using px.scatter, how do I mark one data point with a red star?
fig = px.scatter(df, x="sepal_width", y="sepal_length")
# Now set a single data point to color="red", symbol="star".
This isn't really highlighting an already existing data point within a trace you've already produced, but rather adding another one with a different visual appearance. But it does exactly what you're looking for:
fig.add_trace(go.Scatter(x=[3.5], y=[6.5], mode = 'markers',
marker_symbol = 'star',
marker_size = 15))
Plot:
Complete code:
import plotly.express as px
import pandas as pd
import plotly.graph_objects as go
df = px.data.iris() # iris is a pandas DataFrame
fig = px.scatter(df, x="sepal_width", y="sepal_length")
fig.add_trace(go.Scatter(x=[3.5], y=[6.5], mode = 'markers',
marker_symbol = 'star',
marker_size = 15))
fig.show()
This directly modifies the Scatter trace's Marker itself:
import plotly.express as px
df = px.data.iris()
fig = px.scatter(df, x="sepal_width", y="sepal_length")
trace = next(fig.select_traces())
# Modify kth point.
n = len(trace.x)
k = 136
color = [trace.marker.color] * n
color[k] = "red"
size = [8] * n
size[k] = 15
symbol = [trace.marker.symbol] * n
symbol[k] = "star"
# Update trace.
trace.marker.color = color
trace.marker.size = size
trace.marker.symbol = symbol
# Alternatively, call:
# fig.update_traces(marker=dict(color=color, size=size, symbol=symbol))
fig.show()

How to format plotly legend when using marker color?

I want to follow up on this post: Plotly: How to colorcode plotly graph objects bar chart using Python?.
When using plotly express, and specifying 'color', the legend is correctly produced as seen in the post by vestland.
This is my plotly express code:
data = {'x_data': np.random.random_sample((5,)),
'y_data': ['A', 'B', 'C', 'D', 'E'],
'c_data': np.random.randint(1, 100, size=5)
}
df = pd.DataFrame(data=data)
fig = px.bar(df,
x='x_data',
y='y_data',
orientation='h',
color='c_data',
color_continuous_scale='YlOrRd'
)
fig.show()
But when using go.Bar, the legend is incorrectly displayed as illustrated here:
This is my code using graph objects:
bar_trace = go.Bar(name='bar_trace',
x=df['x_data'],
y=df['y_data'],
marker={'color': df['c_data'], 'colorscale': 'YlOrRd'},
orientation='h'
)
layout = go.Layout(showlegend=True)
fig = go.FigureWidget(data=[bar_trace], layout=layout)
fig.show()
I'm learning how to use FigureWidget and it seems it can't use plotly express so I have to learn how to use graph objects to plot. How do I link the legend to the data such that it works like the plotly express example in vestland's post.
This really comes down to understanding what a high level API (plotly express) does. When you specify color in px if it is categorical it creates a trace per value of categorical. Hence the below two ways of creating a figure are mostly equivalent. The legend shows an item for each trace, not for each color.
import pandas as pd
import plotly.express as px
import plotly.graph_objects as go
import numpy as np
df = pd.DataFrame({"x":np.linspace(0,10,10), "y":np.linspace(5,15,10), "color":np.random.choice(list("ABCD"),10)})
px.bar(df, x="x", y="y", color="color", orientation="h").show()
fig = go.Figure()
for g in df.groupby("color"):
fig.add_trace(go.Bar(x=g[1]["x"], y=g[1]["y"], name=g[0], orientation="h"))
fig
supplementary based on comments
you do not have to use graph objects if you are using FigureWidget() as demonstrated by second figure, create with plotly express and then generate FigureWidget()
for continuous data normal pattern is to use a single trace and a colorbar (also demonstrated in second figure). However if you want a discrete legend, create a trace per value in c_data and use https://plotly.com/python-api-reference/generated/plotly.colors.html sample_colorscale()
import plotly.express as px
import plotly.colors
import plotly.graph_objects as go
import numpy as np
import pandas as pd
# simulate data frame...
df = pd.DataFrame(
{
"x_data": np.linspace(0, 10, 10),
"y_data": np.linspace(5, 15, 10),
"c_data": np.random.randint(0, 4, 10),
}
)
# build a trace per value in c_data using graph objects ... correct legend !!??
bar_traces = [
go.Bar(
name="bar_trace",
x=d["x_data"],
y=d["y_data"],
marker={
"color": plotly.colors.sample_colorscale(
"YlOrRd",
d["c_data"] / df["c_data"].max(),
)
},
orientation="h",
)
for c, d in df.groupby("c_data")
]
layout = go.Layout(showlegend=True)
fig = go.FigureWidget(data=bar_traces, layout=layout)
fig.show()
fig = px.bar(
df,
x="x_data",
y="y_data",
color="c_data",
orientation="h",
color_continuous_scale="YlOrRd",
)
fig = go.FigureWidget(data=fig.data, layout=fig.layout)
fig.show()

How do I combine two plots into one figure using Plotly?

I have 2 csv files, my codes are as below.
df = pd.read_csv("test.csv",
sep='\t',skiprows=range(9),names=['A', 'B', 'C','D'])
df2 = pd.read_csv("LoadMatch_Limit.csv",skiprows=range(1),names=['X','Y'])
fig = px.line([df,df2], x=['A','X'] , y=['D','Y'])
I would like my line chart, x-axis to take from (columns 'A' and 'X') and my y-axis to take from (columns 'D' and 'Y').
Is there anyway I can plot these 2 charts as one figure?
You could create the two plots and combine them with plotly graph objects
import plotly.express as px
import plotly.graph_objects as go
fig1 = px.line(df, x='A', y='D')
fig2 = px.line(df2, x='X', y='Y')
fig = go.Figure(data = fig1.data + fig2.data)
fig.show()
Plotly.offline has no attribute line. You need to use the graph object to plot two graphs in a single figure. A simple example is shown below(run the code below and see the output graph)
import numpy as np
import pandas as pd
import plotly.offline as py
import plotly.graph_objs as go
from plotly import tools
df1 = pd.DataFrame({"X":np.linspace(0,30,10), "Y":np.random.rand(10)})
df2 = pd.DataFrame({"A":np.linspace(0,40,10), "B":np.random.rand(10)})
# plotting the graphs...
# 'rgb(128, 0, 128)'
# color=sns.color_palette()
def scatter_chart(x, y, color, name):
trace = go.Scatter(
x=x.values,
y=y.values,
name=name,
marker=dict(
color=color,
line=dict(
color=color,
width=1)
),
)
return trace
trace1 = scatter_chart(df2["A"], df2["B"], 'rgb(128, 0, 128)', "df2")
trace2 = scatter_chart(df1["X"], df1["Y"], 'rgba(50, 171, 96, 0.6)', "df1")
fig = tools.make_subplots(rows=1,cols=1, vertical_spacing=0.5)
fig.add_trace(trace1)
fig.add_trace(trace2)
fig.update_layout(
title="df2 and df1 plot",
height=600,
width=600,
# annotations=annotations,
xaxis=dict(tickangle=-45),
legend=dict(x=0.029, y=1.038, font_size=10),
margin=dict(l=100, r=20, t=70, b=70),
paper_bgcolor='rgb(248, 248, 255)',
plot_bgcolor='rgb(248, 248, 255)',)
py.iplot(fig, filename='pageviews_plots_4')

How to make Plotly average out observations at a single x-value Python

This is my dataset:
import seaborn as sns
import plotly.graph_objs as go
x = [0,0,0,1,1,1,2,2,2]
y = [1,2,3,4,5,6,7,8,9]
Using:
sns.lineplot(x=x, y=y)
I get following figure:
I would like to get the same (at least similar result) in Plotly. Currently I have:
fig = go.Figure()
fig.add_trace(go.Scatter(x=x,
y=y,
mode='lines',
name='predictions',
fill="toself"))
However this is the result I obtain which I am not happy with:
Is it a matter of some specific keyword argument passed to fill? Thanks!
Plotly it's not meant to be a "statistical data visualization library" as seaborn so you should prepare the traces before to plot. For your given example you could do something like
import pandas as pd
import plotly.graph_objs as go
x = [0,0,0,1,1,1,2,2,2]
y = [1,2,3,4,5,6,7,8,9]
df = pd.DataFrame({"x": x, "y": y})
grp = df.groupby("x").agg({"y":{"mean", "min", "max"}})
grp.columns = ["_".join(col) for col in grp.columns]
grp = grp.reset_index()
fig = go.Figure()
fig.add_trace(go.Scatter(x=grp["x"],
y=grp["y_min"],
mode='lines',
name='y_min',
opacity=0.75,
# marker = {"color":"lightblue", "width":0.5},
line=dict(color='lightblue', width=0.5),
showlegend=False
))
fig.add_trace(go.Scatter(x=grp["x"],
y=grp["y_mean"],
mode='lines',
name='prediction',
fill="tonexty",
line=dict(color='lightblue', width=2)
))
fig.add_trace(go.Scatter(x=grp["x"],
y=grp["y_max"],
mode='lines',
name='y_max',
opacity=0.75,
fill="tonexty",
line=dict(color='lightblue', width=0.5),
showlegend=False
))

Set up multiple subplots with moving averages using cufflinks and plotly offline

Im trying to select 4 different product prices from my dataframe and plot their moving average as a subplot (2,2) using plotly cufflinks. I would appreciate if anyone can guide on this.
I tried plotting the price as below.
I came across cufflinks technical analysis which allow me to plot moving average in a cleaner way, however, im not too sure how to apply it yet.
from plotly.offline import download_plotlyjs,init_notebook_mode,plot,iplot
from plotly import tools
import plotly.graph_objs as go
trace1= go.Scatter(name=',milk', x=df.Date, y=df['milk'])
trace2= go.Scatter(name='soap', x=df.Date, y=df['soap'])
trace3= go.Scatter(name='rice', x=df.Date, y=df['rice'])
trace4= go.Scatter(name='water', x=df.Date, y=df['water'])
fig = tools.make_subplots(rows=2, cols=2, subplot_titles=('milk', 'soap',
'rice', 'water'))
fig.append_trace(trace1, 1, 1)
fig.append_trace(trace2, 1, 2)
fig.append_trace(trace3, 2, 1)
fig.append_trace(trace4, 2, 2)
fig['layout'].update(height=1000, width=1800, title='supermarket')
plot(fig, filename='supermarket.html')
I would appreciate if someone could teach me how to use plotly cufflinks to plot four moving averages from the selected columns from a dataframe using plotly offline.
Insert the code section below in a Jupyter Notebook to produce the following plot using cufflinks and plotly offline:
Plot:
Code:
# imports
import plotly
from plotly import tools
import cufflinks as cf
from plotly.offline import download_plotlyjs, init_notebook_mode, plot, iplot
import pandas as pd
import numpy as np
from IPython.core.display import display, HTML
import copy
import plotly.graph_objs as go
####### PART 1 - SETUP AND SAMPLE DATA #######
# setup
display(HTML("<style>.container { width:55% !important; } .widget-select > select {background-color: gainsboro;}</style>"))
init_notebook_mode(connected=True)
np.random.seed(123)
cf.set_config_file(theme='pearl')
# Random data using cufflinks
df = cf.datagen.lines().iloc[:,0:4]
df.columns = ['StockA', 'StockB', 'StockC', 'StockD']
####### PART 2 - FUNCTION FOR MOVING AVERAGES #######
# Function for moving averages
def movingAvg(df, win, keepSource):
"""Add moving averages for all columns in a dataframe.
Arguments:
df -- pandas dataframe
win -- length of movingAvg estimation window
keepSource -- True or False for keep or drop source data in output dataframe
"""
df_temp = df.copy()
# Manage existing column names
colNames = list(df_temp.columns.values).copy()
removeNames = colNames.copy()
i = 0
for col in colNames:
# Make new names for movingAvgs
movingAvgName = colNames[i] + '_MA' #+ str(win)
# Add movingAvgs
df_temp[movingAvgName] = df[col].rolling(window=win).mean()
i = i + 1
# Remove estimates with insufficient window length
df_temp = df_temp.iloc[win:]
# Remove or keep source data
if keepSource == False:
df_temp = df_temp.drop(removeNames,1)
return df_temp
# Add moving averages to df
windowLength = 10
df = movingAvg(df=df, win=windowLength, keepSource = True)
####### PART 3 -PLOTLY RULES #######
# Structure lines / traces for the plots
# trace 1
trace1 = go.Scatter(
x=df.index,
y=df['StockA'],
name='StockA'
)
trace1_ma = go.Scatter(
x=df.index,
y=df['StockA_MA'],
name='StockA_MA'
)
# trace 2
trace2 = go.Scatter(
x=df.index,
y=df['StockB'],
name='StockB'
)
trace2_ma = go.Scatter(
x=df.index,
y=df['StockB_MA'],
name='StockB_MA'
)
# trace 3
trace3 = go.Scatter(
x=df.index,
y=df['StockC'],
name='StockC'
)
trace3_ma = go.Scatter(
x=df.index,
y=df['StockC_MA'],
name='StockC_MA'
)
# trace 4
trace4 = go.Scatter(
x=df.index,
y=df['StockD'],
name='StockD'
)
trace4_ma = go.Scatter(
x=df.index,
y=df['StockD_MA'],
name='StockD_MA'
)
# Structure traces as datasets
data1 = [trace1, trace1_ma]
data2 = [trace2, trace2_ma]
data3 = [trace3, trace3_ma]
data4 = [trace4, trace4_ma]
# Build figures
fig1 = go.Figure(data=data1)
fig2 = go.Figure(data=data2)
fig3 = go.Figure(data=data3)
fig4 = go.Figure(data=data4)
# Subplots setup and layout
figs = cf.subplots([fig1, fig2, fig3, fig4],shape=(2,2))
figs['layout'].update(height=800, width=1200,
title='Stocks with moving averages = '+ str(windowLength))
iplot(figs)

Categories