I want a box plot to be placed on top of a scatter plot.
Neither putting the box trace at first and adding the scatter plot on top nor adding an "layer='below'" attribute leads to the desired result. The box always stays in the back.
Any suggestions?
import plotly.graph_objects as go
import numpy as np
np.random.seed(10)
rand = np.random.uniform(-100, 100, 100)
fig = go.Figure()
fig.add_trace(go.Box(
x=rand,
name='Markers',
line_color='rgba(128, 128, 128, .0)',
fillcolor='darkgrey'
))
fig.add_trace(go.Scatter(
x=rand,
y=['Markers']*len(rand),
name='Markers',
mode="markers",
marker_color='orange',
marker_size=8,
# layer='below' # does not work
))
fig.show()
As suggested here, you have to attach the box plot to another axis:
fig = go.Figure()
fig.add_trace(go.Box(
x=rand,
name='Markers',
line_color='rgba(128, 128, 128, .0)',
fillcolor='darkgrey',
yaxis='y2'
))
fig.add_trace(go.Scatter(
x=rand,
y=['Markers']*len(rand),
name='Markers',
mode="markers",
marker_color='orange',
marker_size=8
# layer='below' # does not work
))
fig.update_layout(yaxis2=dict(
matches='y',
layer="above traces",
overlaying="y",
),)
fig.show()
Related
I am struggling to put a cross sign in certain positions of each subplots of plotly in Python. I have 2 subplots and in each one, I want to out the cross in certain positions as below.
Position of the cross sign at the subplot_1 and 2 are attached.
import numpy as np
import plotly.graph_objs as go
import plotly.figure_factory as ff
from plotly.subplots import make_subplots
import string
#Define data for heatmap
N=5
x = np.array([10*k for k in range(N)])
y = np.linspace(0, 2, N)
z1 = np.random.randint(5,15, (N,N))
z2 = np.random.randint(10,27, (N,N))
mytext = np.array(list(string.ascii_uppercase))[:25].reshape(N,N)
fig1 = ff.create_annotated_heatmap(z1, x.tolist(), y.tolist(), colorscale='matter')
fig2 = ff.create_annotated_heatmap(z2, x.tolist(), y.tolist(), annotation_text=mytext, colorscale='Viridis')
fig = make_subplots(
rows=1, cols=2,
horizontal_spacing=0.05,
)
fig.add_trace(fig1.data[0], 1, 1)
fig.add_trace(fig2.data[0], 1, 2)
annot1 = list(fig1.layout.annotations)
annot2 = list(fig2.layout.annotations)
for k in range(len(annot2)):
annot2[k]['xref'] = 'x2'
annot2[k]['yref'] = 'y2'
fig.update_layout(annotations=annot1+annot2)
There are two ways to deal with this question: the first is to use the line mode of the scatterplot and the second is to add a shape. In the line mode of the scatterplot, the real starting position is -0.5, so the heatmap and the cross line are misaligned. So I chose to add a figure.
Also, I can now annotate without using figure_factory, so I'll use a graph object to construct the graph. The configuration is one heatmap combined with two shapes, with the y-axis and x-axis scales changed.
import numpy as np
import plotly.graph_objs as go
from plotly.subplots import make_subplots
np.random.seed(1)
fig = make_subplots(rows=1,
cols=2,
horizontal_spacing=0.05,
)
fig.add_trace(go.Heatmap(z=z1,
text=z1,
texttemplate='%{text}',
showscale=False,
),
row=1,col=1
)
fig.add_shape(type='line',
x0=1.5, y0=1.5, x1=2.5, y1=2.5,
line=dict(color='black', width=2)
)
fig.add_shape(type='line',
x0=2.5, y0=1.5, x1=1.5, y1=2.5,
line=dict(color='black', width=2)
)
fig.add_trace(go.Heatmap(z=z2,
text=mytext,
texttemplate='%{text}',
showscale=False,
colorscale = 'Viridis'
),
row=1,col=2
)
fig.add_shape(type='line',
x0=0.5, y0=-0.5, x1=1.5, y1=0.5,
line=dict(color='black', width=2),
row=1,col=2
)
fig.add_shape(type='line',
x0=1.5, y0=-0.5, x1=0.5, y1=0.5,
line=dict(color='black', width=2),
row=1, col=2
)
fig.update_yaxes(tickvals=[0,1,2,3,4], ticktext=y.tolist())
fig.update_xaxes(tickvals=[0,1,2,3,4], ticktext=x.tolist())
fig.update_layout(autosize=False, width=800)
fig.show()
I have a bar plot that resembles this something like this-
import plotly.graph_objects as go
months = ["ABC","XYZ"]
fig = go.Figure()
fig.add_trace(go.Bar(
x=months,
y=[3.95,4.04],
name='SMD',
marker_color='yellow'
))
fig.add_trace(go.Bar(
x=months,
y=[3.78,4.06],
name='Camrest',
marker_color='black'
))
fig.add_trace(go.Bar(
x=months,
y=[4.16,4.28],
name='MWOZ 2.1',
marker_color='cadetblue'
))
fig.update_layout(barmode='group', template="plotly_white")
fig.show()
I would like to anti-clockwise rotate the bar plot by 45 degrees, that is, horizontally orient the bar graph. How can I achieve this?
Also, how can I add a custom label to the y-axis as it currently only has the number scale and no axis name?
A horizontal bar graph can be created by reversing the x- and y-axes of a normal bar graph and specifying the graph direction. In addition, the y-axis is reversed. Refer to this in the official reference.
import plotly.graph_objects as go
months = ["ABC","XYZ"]
fig = go.Figure()
fig.add_trace(go.Bar(
y=months,
x=[3.95,4.04],
name='SMD',
marker_color='yellow',
orientation='h'
))
fig.add_trace(go.Bar(
y=months,
x=[3.78,4.06],
name='Camrest',
marker_color='black',
orientation='h'
))
fig.add_trace(go.Bar(
y=months,
x=[4.16,4.28],
name='MWOZ 2.1',
marker_color='cadetblue',
orientation='h'
))
fig.update_layout(barmode='group', template="plotly_white", yaxis=dict(autorange='reversed'))
fig.show()
I am trying to overlay a point over a boxplot with Plotly and Python. I am able to add two traces to the same graph, but I couldn't find a way to make the extra point closer to the boxplot.
This is the image I get:
and the code that generates it is:
x = np.fromiter(duplicates.values(), dtype=float)
fig = go.Figure()
fig.update_layout(autosize=False, width=400, height=150, paper_bgcolor="White", plot_bgcolor='rgba(0,0,0,0)',
hovermode=False, margin=dict(l=10, r=10, b=10, t=10, pad=4),
boxmode='group', boxgroupgap=0.25,
boxgap=0.25,
)
fig.add_trace(go.Box(x=x, showlegend=False))
fig.add_trace(go.Scatter(x=np.array(duplicates[sample_id]), y=np.array(0), mode='markers', showlegend=False))
fig.update_xaxes(title='')
fig.update_yaxes(showticklabels=False)
my_div = plotly.offline.plot(fig, output_type='div',
show_link=False,
config=dict(
displayModeBar=False
))
I know there is the hovertemplate/hover_text/ option for traces (marker/line) but I cannot find such a thing for shapes.
Is there a way to have a hover text pop up when moving over a shape? Maybe a workaround?
Example:
import plotly.graph_objects as go
fig = go.Figure()
fig.add_trace(go.Scatter(
x=[1.5, 3],
y=[2.5, 2.5],
text=["Rectangle reference to the plot",
"Rectangle reference to the axes"],
mode="markers",
))
fig.add_shape(
# Rectangle reference to the plot
type="rect",
xref="paper",
yref="paper",
x0=0.25,
y0=0,
x1=0.5,
y1=0.5,
line=dict(
color="LightSeaGreen",
width=3,
),
fillcolor="PaleTurquoise",
)
When I hover over the two points, I get a hover-template with information. How can I get something similar for the shape?
It seems that it's not possible to add hoverinfo to shapes directly. But you can obtain something very close to what seems to be the desired effect through the right combination of shapes and traces. The following plot is made from specifying two rectangles in a list like:
shapes = [[2,6,2,6],
[4,7,4,7]]
The rest of the code snippet is set up to be flexible with regards to the number of shapes, and the colors assigned to them and the corresponding traces to make that little dot in the lower right corners of the shapes.
Plot:
If this is something you can use, we can discuss ways to edit what is being displayed in the hoverinfo.
Complete code:
# Imports
import pandas as pd
#import matplotlib.pyplot as plt
import numpy as np
import plotly.graph_objects as go
import plotly.express as px
# shape definitions
shapes = [[2,6,2,6],
[4,7,4,7]]
# color management
# define colors as a list
colors = px.colors.qualitative.Plotly
# convert plotly hex colors to rgba to enable transparency adjustments
def hex_rgba(hex, transparency):
col_hex = hex.lstrip('#')
col_rgb = list(int(col_hex[i:i+2], 16) for i in (0, 2, 4))
col_rgb.extend([transparency])
areacol = tuple(col_rgb)
return areacol
rgba = [hex_rgba(c, transparency=0.4) for c in colors]
colCycle = ['rgba'+str(elem) for elem in rgba]
# plotly setup
fig = go.Figure()
# shapes
for i, s in enumerate(shapes):
fig.add_shape(dict(type="rect",
x0=s[0],
y0=s[2],
x1=s[1],
y1=s[3],
layer='above',
fillcolor=colCycle[i],
line=dict(
color=colors[i],
width=3)))
# traces as dots in the lower right corner for each shape
for i, s in enumerate(shapes):
fig.add_trace(go.Scatter(x=[s[1]], y=[s[2]], name = "Hoverinfo " +str(i + 1),
showlegend=False,
mode='markers', marker=dict(color = colors[i], size=12)))
# edit layout
fig.update_layout(yaxis=dict(range=[0,8], showgrid=True),
xaxis=dict(range=[0,8], showgrid=True))
fig.show()
I thought of a solution I am happy with.
Simply draw a shape. You won't be able to see a hover text. However, if you add a trace with a fill on top of the shape, then set the trace to opacity=0 you will see the hover text from the trace pop up when moving over the shape.
Again, thanks for your responses!
import plotly.graph_objects as go
# Draw shape (you won't be able to add a hover text for it)
fig = go.Figure()
fig.add_shape(
type="rect",
x0=0, y0=0,
x1=4, y1=3,
fillcolor='LightSkyBlue',
line_color='Blue',
name='Shape 1'
)
# Adding a trace with a fill, setting opacity to 0
fig.add_trace(
go.Scatter(
x=[0,0,4,4,0],
y=[0,3,3,0,0],
fill="toself",
mode='lines',
name='',
text='Custom text on top of shape',
opacity=0
)
)
fig.show()
I made a line graph with the code below and I'm trying to add a horizontal line at y=1. I tried following the instructions on the plotly site but it is still not showing. Does anyone know why?
date = can_tot_df.date
growth_factor = can_tot_df.growth_factor
trace0 = go.Scatter(
x=date,
y=growth_factor,
mode = 'lines',
name = 'growth_factor'
)
fig = go.Figure()
fig.add_shape(
type='line',
x0=date.min(),
y0=1,
x1=date.max(),
y1=1,
line=dict(
color='Red',
)
)
data = [trace0]
iplot(data)
Short answer, and a general solution:
fig.add_shape(type='line',
x0=0,
y0=40,
x1=8,
y1=40,
line=dict(color='Red',),
xref='x',
yref='y'
)
Details and specifics about OP's question
It's hard to tell exactly what's wrong without a sample of your data.
What I can tell for sure is that you're missing the arguments xref and yref to specify that the line is drawn as units of your y and x axis. Judging by your sample code, this is what you'd like to do since you're specifying your x-values in terms of dates.
Also, you don't need to worry about iplot for newer versions of plotly. You can display your chart just as easily by just running fig.show(). The figure and code sample below will show you how to use fig.show() and how to define your lines in terms of axis units.
Plot:
Code:
import plotly.graph_objects as go
import numpy as np
x = np.arange(10)
fig = go.Figure(data=go.Scatter(x=x, y=x**2))
fig.add_shape(type='line',
x0=0,
y0=40,
x1=8,
y1=40,
line=dict(color='Red',),
xref='x',
yref='y'
)
fig.show()
An alternative to xref='x' is xref='paper'. Now you can specify x0 as a float between 0 and 1 spanning from the start and end of the plot.
You could also use fig.add_hline(y=1) --> see https://plotly.com/python/horizontal-vertical-shapes/
import plotly.graph_objects as go
import numpy as np
x = np.arange(10)
fig = go.Figure(data=go.Scatter(x=x, y=x**2))
fig.add_hline(y=40, line_width=3, line_dash="dash", line_color="green")
fig.show()
If you use subplots, then this is the easiest way I found to add an other line to a subplot. this example draws a horizontal line at y=80 for all x values
from plotly.subplots import make_subplots
fig = make_subplots(rows=2, cols=1,
shared_xaxes=True,
vertical_spacing=0.02)
[some graph]
fig.add_trace(go.Scatter(
name='Y=80',
x = [df['date'].min(), df['date'].max()],
y = [80, 80],
mode = "lines",
marker = dict(color = 'rgba(80, 26, 80, 0.8)')
),row=1, col=1)
i found the solution on github :
df = df
fig = px.scatter(df, x="date", y="growth_factor", mode = 'lines',
hover_name=df['growth_factor'] )
fig.update_layout(shapes=[
dict(
type= 'line',
yref= 'y', y0= 1, y1= 1, # adding a horizontal line at Y = 1
xref= 'paper', x0= 0, x1= 1
)
])
fig.show()
You’re adding the line to your fig object, but fig is not getting passed into the iplot() function, only your data. So only the trace is getting plotted.
If you're using a late version of plotly, the new syntax allows you to create this plot simply using the fig object, like:
from plotly import graph_objects as go
fig = go.Figure()
# Contrived dataset for example.
x = [1, 2, 3, 4]
y = [i**2 for i in x]
fig.add_trace(go.Scatter(
x=x,
y=y,
mode = 'lines',
name = 'growth_factor'))
fig.add_shape(type='line',
x0=min(x),
y0=5,
x1=max(x),
y1=5,
line=dict(color='Red'))
fig.update_shapes(dict(xref='x', yref='y'))
fig.show()
Here are the plotly docs for convenience.