Here is the code that I have tried:
# import pandas as pd
import numpy as np
import plotly.graph_objects as go
from plotly.subplots import make_subplots
df = pd.read_csv("resultant_data.txt", index_col = 0, sep = ",")
display=df[["Velocity", "WinLoss"]]
pos = lambda col : col[col > 0].sum()
neg = lambda col : col[col < 0].sum()
Related_Display_Info = df.groupby("RacerCount").agg(Counts=("Velocity","count"),
WinLoss=("WinLoss","sum"),
Positives=("WinLoss", pos),
Negatives=("WinLoss", neg),
)
# Create figure with secondary y-axis
fig = make_subplots(specs=[[{"secondary_y": True}]])
# Add traces
fig.add_trace(
go.Scatter(x=display.index, y=display["Velocity"], name="Velocity", mode="markers"),
secondary_y=False
)
fig.add_trace(
go.Scatter(x=Related_Display_Info.index,
y=Related_Display_Info["WinLoss"],
name="Win/Loss",
mode="markers",
marker=dict(
color=(
(Related_Display_Info["WinLoss"] < 0)
).astype('int'),
colorscale=[[0, 'green'], [1, 'red']]
)
),
secondary_y=True,
)
# Add figure title
fig.update_layout(
title_text="Race Analysis"
)
# Set x-axis title
fig.update_xaxes(title_text="<b>Racer Counts</b>")
# Set y-axes titles
fig.update_yaxes(title_text="<b>Velocity</b>", secondary_y=False)
fig.update_yaxes(title_text="<b>Win/Loss/b>", secondary_y=True)
fig.update_layout(hovermode="x unified")
fig.show()
The output is:
But I was willing to display the following information when I hover on the point:
RaceCount = From Display dataframe value Number of the race corresponding to the dot I hover on.
Velocity = From Display Dataframe value Velocity at that point
Counts = From Related_Display_Info Column
WinLoss = From Related_Display_Info Column
Positives = From Related_Display_Info Column
Negatives = From Related_Display_Info Column
Please can anyone tell me what to do to get this information on my chart?
I have checked this but was not helpful since I got many errors: Python/Plotly: How to customize hover-template on with what information to show?
Data:
RacerCount,Velocity,WinLoss
111,0.36,1
141,0.31,1
156,0.3,1
141,0.23,1
147,0.23,1
156,0.22,1
165,0.2,1
174,0.18,1
177,0.18,1
183,0.18,1
114,0.32,1
117,0.3,1
120,0.29,1
123,0.29,1
126,0.28,1
129,0.27,1
120,0.32,1
144,0.3,1
147,0.3,1
159,0.27,1
165,0.26,1
168,0.25,1
156,0.29,1
165,0.26,1
168,0.26,1
165,0.28,1
213,0.17,1
243,0.15,1
249,0.14,1
228,0.54,1
177,0.67,1
180,0.66,1
183,0.65,1
192,0.66,1
195,0.62,1
198,0.6,1
180,0.66,1
222,0.56,1
114,0.41,1
81,0.82,1
102,0.56,1
111,0.55,1
90,1.02,1
93,1.0,1
90,1.18,1
90,1.18,1
93,1.1,1
96,1.07,1
99,1.04,1
102,0.99,1
105,0.94,1
108,0.92,1
111,0.9,1
162,0.66,1
159,0.63,1
162,0.65,-1
162,0.66,-1
168,0.64,-1
159,0.68,-1
162,0.67,-1
174,0.62,-1
168,0.65,-1
171,0.64,-1
198,0.55,-1
300,0.47,-1
201,0.56,-1
174,0.63,-1
180,0.61,-1
171,0.64,-1
174,0.62,-1
303,0.47,-1
312,0.48,-1
258,0.51,-1
261,0.51,-1
264,0.5,-1
279,0.47,-1
288,0.48,-1
294,0.47,-1
258,0.52,-1
261,0.51,-1
267,0.5,-1
222,0.53,-1
171,0.64,-1
177,0.63,-1
177,0.63,-1
Essentially, this code ungroups the data frame before plotting to create the hovertemplate you're looking for.
As stated in the comments, the data has to have the same number of rows to be shown in the hovertemplate. At the end of my answer, I added the code all in one chunk.
Since you have hovermode as x unified, you probably only want one of these traces to have hover content.
I slightly modified the creation of Related_Display_Info. Instead of WinLoss, which is already in the parent data frame, I modified it to WinLoss_sum, so there wouldn't be a naming conflict when I ungrouped.
Related_Display_Info = df.groupby("RacerCount").agg(
Counts=("Velocity","count"), WinLoss_sum=("WinLoss","sum"),
Positives=("WinLoss", pos), Negatives=("WinLoss", neg))
Now it's time to ungroup the data you grouped. I created dui (stands for display info ungrouped).
dui = pd.merge(df, Related_Display_Info, how = "outer", on="RacerCount",
suffixes=(False, False))
I created the hovertemplate for both traces. I passed the entire ungrouped data frame to customdata. It looks like the only column that isn't in the template is the original WinLoss.
# create hover template for all traces
ht="<br>".join(["<br>RacerCount: %{customdata[0]}",
"Velocity: %{customdata[1]:.2f}",
"Counts: %{customdata[3]}",
"Winloss: %{customdata[4]}",
"Positives: %{customdata[5]}",
"Negatives: %{customdata[6]}<br>"])
The creation of fig is unchanged. However, the traces are both based on dui. Additionally, the index isn't RacerCount, so I used the literal field instead.
# Create figure with secondary y-axis
fig = make_subplots(specs=[[{"secondary_y": True}]])
# Add traces
fig.add_trace(go.Scatter(x=dui["RacerCount"], y=dui["Velocity"],
name="Velocity", mode="markers",
customdata=dui, hovertemplate=ht),
secondary_y=False)
fig.add_trace(
go.Scatter(x = dui["RacerCount"], y=dui["WinLoss_sum"], customdata=dui,
name="Win/Loss", mode="markers",
marker=dict(color=((dui["WinLoss_sum"] < 0)).astype('int'),
colorscale=[[0, 'green'], [1, 'red']]),
hovertemplate=ht),
secondary_y=True)
All the code altogether (for easier copy + paste)
import pandas as pd
import numpy as np
import plotly.graph_objects as go
from plotly.subplots import make_subplots
df = pd.read_clipboard(sep = ',')
display=df[["Velocity", "WinLoss"]]
pos = lambda col : col[col > 0].sum()
neg = lambda col : col[col < 0].sum()
Related_Display_Info = df.groupby("RacerCount").agg(
Counts=("Velocity","count"), WinLoss_sum=("WinLoss","sum"),
Positives=("WinLoss", pos), Negatives=("WinLoss", neg))
# ungroup the data for the hovertemplate
dui = pd.merge(df, Related_Display_Info, how = "outer", on="RacerCount",
suffixes=(False, False))
# create hover template for all traces
ht="<br>".join(["<br>RacerCount: %{customdata[0]}",
"Velocity: %{customdata[1]:.2f}",
"Counts: %{customdata[3]}",
"Winloss: %{customdata[4]}",
"Positives: %{customdata[5]}",
"Negatives: %{customdata[6]}<br>"])
# Create figure with secondary y-axis
fig = make_subplots(specs=[[{"secondary_y": True}]])
# Add traces
fig.add_trace(go.Scatter(x=dui["RacerCount"], y=dui["Velocity"],
name="Velocity", mode="markers",
customdata=dui, hovertemplate=ht),
secondary_y=False)
fig.add_trace(
go.Scatter(x = dui["RacerCount"], y=dui["WinLoss_sum"], customdata=dui,
name="Win/Loss", mode="markers",
marker=dict(color=((dui["WinLoss_sum"] < 0)).astype('int'),
colorscale=[[0, 'green'], [1, 'red']]),
hovertemplate=ht),
secondary_y=True)
# Add figure title
fig.update_layout(
title_text="Race Analysis"
)
# Set x-axis title
fig.update_xaxes(title_text="<b>Racer Counts</b>")
# Set y-axes titles
fig.update_yaxes(title_text="<b>Velocity</b>", secondary_y=False)
fig.update_yaxes(title_text="<b>Win/Loss/b>", secondary_y=True)
fig.update_layout(hovermode="x unified")
fig.show()
I want to draw multiple CSV files on an HTML page with fig = make_subplots(rows=.., cols=..).
df1 = pd.read_csv('first_input.csv')
fig1 = px.scatter(df, x="...", y="...", color="..")
df2 = pd.read_csv('first_input.csv')
fig2 = px.scatter(df, x="...", y="...", color="..")
Unfortunately plotly subplots do not directly support plotly.express figures as explained in the documentation here.
However, when you create a plotly.express figure using fig1 = px.scatter(df, x="...", y="...", color=".."), you are actually creating a figure where fig1.data is a tuple of go.Scatter traces. You can access each trace in fig1.data and add it to your subplots object.
If you have multiple px.scatter figures, you can iterate through them, and add each trace from px.scatter figure to your subplots object at the appropriate row and column. Then we can add the axes titles from each px.scatter figure to the subplots object layout.
I'll use the tips sample dataset to demonstrate:
import plotly.express as px
from plotly.subplots import make_subplots
df = px.data.tips()
fig1 = px.scatter(df, x="total_bill", y="tip", color="smoker")
fig2 = px.scatter(df, x="total_bill", y="tip", color="day")
fig_subplots = make_subplots(rows=2, cols=1)
for trace in fig1.data:
fig_subplots.add_trace(
trace,
row=1, col=1
)
for trace in fig2.data:
fig_subplots.add_trace(
trace,
row=2, col=1
)
## x and y axies in fig_subplots["layout"] are called xaxis, xaxis2, ..., yaxis, yaxis2, ...
## here we are making the assumption you are stacking your plots vertically
def modify_axis_titles(fig_subplots, px_fig, nrow):
xaxis_name, yaxis_name = f"xaxis{nrow}", f"yaxis{nrow}"
fig_subplots['layout'][xaxis_name]['title'] = px_fig.layout['xaxis']['title']
fig_subplots['layout'][yaxis_name]['title'] = px_fig.layout['yaxis']['title']
for px_fig, nrow in zip([fig1, fig2],[1,2]):
modify_axis_titles(fig_subplots, px_fig, nrow)
fig_subplots.show()
I am using plotly with python and I am trying to use use these kinds of tick in X and Y axis:
10-3, 10-4, 10-5, and so on..
Any suggestions or recoomended reading?
I am obtaining this:
I was also in a search for this feature, and found the solution in this other answer:
https://stackoverflow.com/a/56742105/418875
You should set exponentformat to the power option. This will print the ticks as shown below:
I believe the closes you'll get is logartihmic axes:
import plotly.express as px
df = px.data.gapminder().query("year == 2007")
fig = px.scatter(df, x="gdpPercap", y="lifeExp", hover_name="country", log_x=True)
fig.show()
This has been bugging me for a while, here's the best solution I've found:
TLDR, you can use HTML formatting to make sure the exponent is a superscript and use array mode to pass strings for the tick labels to plotly.
import plotly.express as px
import numpy as np
df = px.data.gapminder().query("year == 2007")
fig = px.scatter(df, x="gdpPercap", y="lifeExp", hover_name="country", log_x=True)
tickvals = np.logspace(3,6, num=4)
print(tickvals)
def format_tick(n: float):
m, e = f"{n:.0e}".split("e")
e = int(e)
return f"{m} x 10<sup>{e}</sup>"
ticktext = [format_tick(t) for t in tickvals]
print(ticktext)
fig.update_layout(
xaxis = dict(
tickmode = 'array',
tickvals = tickvals,
ticktext = ticktext,
)
)
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.
I have data points that belong to three different classes. On the other hand, I have weight for each data point in its class. I want to color my points based on their weight, but with three different continuous range of colors. Actually I want something like the following image (which is made by hand). Now I'm using Plotly for coloring, but any other method compatible with python is welcomed.
Actually I want to combine the two output of the code:
if __name__ == '__main__':
n_data = 100
n_class = 3
t1 = [random.random() for i in range(n_data)]
t2 = [random.random() for i in range(n_data)]
class_color = [str(random.randint(1,n_class)) for i in range(n_data)]
weight_color = [random.random() for i in range(n_data)]
df = pd.DataFrame()
print(len(t1))
print(len(t2))
df['x'] = t1
df['y'] = t2
df['class_color'] = class_color
df['weight_color'] = weight_color
fig1 = px.scatter(df, x="x", y="y", color="class_color")
fig1.show()
fig2 = px.scatter(df, x="x", y="y", color="weight_color")
fig2.show()
Please don't take it as an answer (yet). As far as I can see you can use different color scales with plotly. But you should work on how properly show all legends
import plotly.graph_objects as go
import plotly.express as px
df = px.data.iris()
dfs = [d[1] for d in list(df.groupby('species'))]
fig = go.Figure()
fig.add_trace(
go.Scatter(x=dfs[0]["sepal_width"],
y=dfs[0]["sepal_length"],mode="markers",
marker=dict(color=dfs[0]["sepal_length"],
colorscale='Viridis',
showscale=True),
name=dfs[0]["species"].unique()[0],
showlegend=False
))
fig.add_trace(
go.Scatter(x=dfs[1]["sepal_width"],
y=dfs[1]["sepal_length"],mode="markers",
marker=dict(color=dfs[1]["sepal_length"],
colorscale='Magenta',
showscale=False),
name=dfs[1]["species"].unique()[0],
showlegend=False
))
fig.add_trace(
go.Scatter(x=dfs[2]["sepal_width"],
y=dfs[2]["sepal_length"],mode="markers",
marker=dict(color=dfs[2]["sepal_length"],
colorscale='Cividis',
showscale=False),
name=dfs[2]["species"].unique()[0],
showlegend=False
))