Issue
I'm using Plotly.express, plotly.subplots and plotly.graph_objs to visualize some graphs that vary according to some data (data) that I pass, but that here I put in hard code to save code, it is more readable and simplified.
What I want to achieve is a graph like the one I show next (it is an edited image), with a single label on the y-axes "Value", no labels on the right side, the x-axis would stay as-is with the label " Timeline" and that the x-axis does not separate the values into multiples of 2, but 1 by 1 (and integrate it with the lines from -1 to the last value of the x-axis, I explain at the end):
1st. When I use plotly.express this is the code:
import plotly.express as px
import pandas as pd
import numpy as np
data = {
"Name": [
"Lamp_D_Rq", "Status", "Status", "HMI",
"Lck_D_RqDrv3", "Lck_D_RqDrv3", "Lck_D_RqDrv3",
"Lck_D_RqDrv3", "Lamp_D_Rq", "Lamp_D_Rq",
"Lamp_D_Rq", "Lamp_D_Rq",
],
"Value": [0, 4, 4, 2, 1, 1, 2, 2, 1, 1, 3, 3],
"Gage": [
"F1", "H1", "H3", "H3", "H3",
"F1", "H3", "F1", "F1", "H3",
"F1", "H3",
],
"Id_Par": [0, 0, 0, 11, 0, 0, 0, 0, 0, 0, 0, 0],
}
signals_df = pd.DataFrame(data)
signals_df['Count'] = signals_df.groupby('Id_Par').cumcount().add(1).mask(signals_df['Id_Par'].eq(0), 0)
signals_df['Sub'] = signals_df.index - signals_df['Count']
id_par_prev = signals_df['Id_Par'].unique()
id_par = np.delete(id_par_prev, 0)
signals_df['Prev'] = [1 if x in id_par else 0 for x in signals_df['Id_Par']]
print(signals_df)
fig = px.line(
signals_df,
y="Value",
x="Sub",
color="Name",
hover_data=["Gage"],
custom_data=["Gage"],
markers=True,
height=500,
render_mode="svg",
facet_row="Name"
)
fig.update_traces(line={"shape": 'hv'})
fig.update_traces(
hovertemplate="<br>".join([
"Gage: %{customdata[0]}",
]))
fig.update_layout(
hovermode="x",
title="Saving/Loss diagram",
legend_title="CAN Singals",)
fig.update_xaxes(matches='x')
fig.show(config={'displaylogo': False})
In the execution of this first code, I get the following, the Value tag repeated by subplot and with the names spliced on the right side, even these values have the smallest names that I found, there are much longer names, that is why the I want to delete, but I can't find the option, however, I was thinking to remove Name and change the orientation to horizontal and the x-axis values separated by multiples of 2, I would like to present them 1 by 1, but I cannot find any of these parameters or options for Plotly:
2nd. When I use plotly.subplots and plotly.graph_objs the code is:
from plotly.subplots import make_subplots
import plotly.graph_objs as go
import pandas as pd
import numpy as np
data = {
"Name": [
"Lamp", "Status", "Status", "M1",
"Lock", "Lock", "Lock",
"Lock", "Lamp", "Lamp",
"Lamp", "Lamp",
],
"Value": [0, 4, 4, 2, 1, 1, 2, 2, 1, 1, 3, 3],
"Gage": [
"A1", "B1", "B3", "B3", "B3",
"A1", "B3", "A1", "A1", "B3",
"A1", "B3",
],
"Id_Par": [0, 0, 0, 11, 0, 0, 0, 0, 0, 0, 0, 0],
}
signals_df = pd.DataFrame(data)
signals_df['Count'] = signals_df.groupby('Id_Par').cumcount().add(1).mask(signals_df['Id_Par'].eq(0), 0)
signals_df['Sub'] = signals_df.index - signals_df['Count']
id_par_prev = signals_df['Id_Par'].unique()
id_par = np.delete(id_par_prev, 0)
signals_df['Prev'] = [1 if x in id_par else 0 for x in signals_df['Id_Par']]
print(signals_df)
names_signals = signals_df['Name'].unique()
fig = make_subplots(rows=len(names_signals), cols=1,
shared_xaxes=True,
vertical_spacing=0.02)
for i, name_signal in enumerate(names_signals):
fig.add_trace(go.Scatter(x=signals_df["Sub"],
y=signals_df["Value"],
line_shape='hv',
# facet_row="Name")
))
fig.update_layout(
hovermode="x",
title="Saving/Loss diagram",
legend_title="CAN Singals",)
fig.update_xaxes(matches='x')
fig.show(config={'displaylogo': False})
In the execution of the second code, which is a test of what I have been doing to see if it is easier for me to visualize the data, but it gives me an error that it does not find the facet_row parameter, when I uncomment it and yes, I already looked in it help file from Scatter and I can't find something similar:
In this case, I'm using this because when reviewing the Plotly documentation I realized that the update_trace
, update_layout
, etc is where you can edit and update these graph parameters, and here how you use add_trace
seems to be a little different, but I need first separate the graph by subplots and I can't find how.
In both cases, the objective is, of some signals from a circuit, to separate the values and graphs by names and subplots, that is, to graph how they vary and the values are presented in a timeline according to their name and painted in different subplots.
Regarding the lines that start from -1 and end up to the last value of the signals, I tried the following, and it does not accept it because it necessarily wants me to pass a column of the signals_df dataframe, but first I want to find the parameters that allow me graph the subplots with a single label on the left y-axis and remove the names on the right side and the x-axis separate it 1x1, then continue with this, which actually served me very well, in a desktop application that I made with Matplotlib, but in this case I would not know how to call these values, since I have tried to put it in variables and assign it to "x" and "y" of px.line and it does not work:
x= np.hstack([-1, data.index.values, len(signals_df) - 1])
y= np.hstack([0, data.values, data.iloc[-1]])
I hope I have been explicit and can help me, I thank you very much.
Solution
- there are multiple questions embedded in this
- px annotations can be removed from layout if required. I don't believe this is the question
- how to use go to dynamically generate sub-plots. Simple, loop over subsets of data with
enumerate()
to define the row. Details below
from plotly.subplots import make_subplots
import plotly.graph_objects as go
names_signals = signals_df['Name'].unique()
fig = make_subplots(rows=len(names_signals), cols=1,
shared_xaxes=True,
vertical_spacing=0.02)
for r, (n, d) in enumerate(signals_df.groupby("Name")):
# gemerate -1 point
d = d.merge(pd.Series(np.arange(-1, d["Sub"].max()+1), name="Sub"), on="Sub", how="right").fillna(0, limit=1).dropna()
fig.add_trace(go.Scatter(name=n, x=d["Sub"], y=d["Value"], line_shape="hv"), row=r+1, col=1)
# finally label axes and set tick sizes
fig.add_annotation(x=-0.05, y=.5, text="Value", xref="paper", yref="paper", textangle=270, showarrow=False)
fig.add_annotation(x=.5, y=-0.2, text="Timeline", xref="paper", yref="paper", showarrow=False)
fig.update_xaxes(dtick=1, tick0=-1)
fig.update_yaxes(dtick=1)
Answered By - Rob Raymond
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.