简体   繁体   中英

Can yaxis be dynamically added into an graph_objects Layout in plotly?

In my practical training that I'm undergoing right now there is a python script that reads a CSV file and plots against selected columns of that file. However the selection of headers is hardcoded, so if anybody wants to use the script they have to manipulate the code. My task is to make it all dynamic, eg the user of the script can select any number of columns via console ( argparse ) and the script automatically creates the traces, creates the layout, adds both to a figure and exports it into a html file.

I have managed to accomplish all of that except for the Layout part. In the current (hardcoded) state of the script, there are these arguments that are passed to the graph_objects.Layout function:

 layout = go.Layout(title=inFile,
                       plot_bgcolor='rgb(230, 230,230)', showlegend=True,
                       yaxis=dict(
                           title=df.columns[y1graph] # Note: 'ygraph' contains the index of the column
                       ),
                       yaxis2=dict(
                            title=df.columns[y2graph],
                            side='right',
                            overlaying='y'
                       ),
                       yaxis3=dict(
                            title=df.columns[y3graph],
                            side='right',
                            overlaying='y'
                       )
                    )

Unfortunately I neither have found a way to make that all dynamic, so that the "yaxis"-arguments are added according the number of selected columns. Nor have I found a way to add titles to the graphs, make them overlay each other and put them to the right side the same way go.Layout does. There is a way of course to add titles with plotly express, but it kinda doesn't do the same thing for me in respect to the overlaying and side arguments.

Any ideas?

Please note: It's my very first question here on stackoverflow so if I did do anything wrong, please advice! Also, if I have left out crucial information please let me know.

  • simulate a CSV, a dataframe with 20 columns
  • simulate user selecting columns to plot (randomly sample 4 columns of the 20)
  • build the figure, assigning a different yaxis to each trace
  • finally as per question, dynamically configure y-axes
import numpy as np
import plotly.express as px
import pandas as pd

# simulate a CSV, 20 columns...
df = pd.DataFrame(
    {
        chr(ord("A") + i): np.random.uniform(miny, miny + 200, 30)
        for i, miny in zip(range(20), np.random.randint(30, 3000, 20))
    }
)

# simulate user passing columns to plot...
cols = pd.Series(df.columns).sample(4).tolist()

# build figure with each trace using it's own yaxis
fig = px.line(df, y=cols).for_each_trace(
    lambda t: t.update(yaxis=f"y{cols.index(t.name)+1 if cols.index(t.name)>0 else ''}")
).update_layout(yaxis={"title":cols[0]})

# dynamically update yaxes...
fig.update_layout(
    {
        t.yaxis.replace("y", "yaxis"): {
            "title": t.name,
            "overlaying": "y",
            "side": "right",
            "position":1-(i/15)
        }
        for i,t in enumerate(fig.data)
        if t.yaxis != "y"
    }
).update_layout(xaxis={"domain":[0,1-(len(cols)*.05)]}) # give some space for additional yaxes

在此处输入图片说明

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM