Search code examples
plotlyplotly-python

change line color in middle of plot - plotly


Creating 12 subplots with plotly from a csv containing rows with 13 values. The last value indicates that the data in that row is estimated from this point until the status changes back in a later row.
Trying to make line graphs that plots a line, changes to red when the status changes to 1, then back to original color when the status changes back to 0. Is this possible?

with lock:
    df = pd.read_csv(OCcsvFile, delimiter=',')

# plotly setup
plot_rows = 4
plot_cols = 3
# Create plot figure
fig = make_subplots(rows=plot_rows, cols=plot_cols, subplot_titles=("Header1", "Header2", "Header3", "Header4", "Header5",
                                                                    "Header6", "Header7", "Header8", "Header9", "Header10",
                                                                    "Header11", "Header12"))

# add traces
x = 1  # column counter
for i in range(1, plot_rows+1):
    for j in range(1, plot_cols+1):
        #print(str(i)+ ', ' + str(j))
        fig.add_trace(go.Scatter(x=df.iloc[:, 0], y=df.iloc[:, x],
                                 name=df.columns[x],
                                 mode='lines'),
                      row=i,
                      col=j)
        x = x+1

Solution

    • taken approach of reshaping dataframe to be ready for plotly express
    • have worked out starting dataframe from description, a sample would be better
    import pandas as pd
    import plotly.express as px
    
    df = pd.DataFrame(
        np.random.randint(1, 10, [100, 12]), columns=[f"c{i+1}" for i in range(12)]
    ).assign(status=np.repeat(np.random.randint(0, 2, 20), 5))
    
    # restructure dataframe for px
    # 1. preserve status in index
    # 2. make columns another level of index
    # 3. make index columns and make column names meaningful
    dfp = (
        df.set_index("status", append=True)
        .stack()
        .reset_index()
        .rename(columns={"level_0": "x", "level_2": "facet", 0: "value"})
    )
    
    # make sure missing values are present as NaN
    dfp = dfp.merge(
        pd.DataFrame(index=pd.MultiIndex.from_product(
            [dfp["x"].unique(), dfp["facet"].unique(), dfp["status"].unique()]
        )),
        left_on=["x", "facet", "status"],
        right_index=True,
        how="right"
    )
    
    # now it's a very simple plot
    px.line(dfp, x="x", y="value", color="status", facet_col="facet", facet_col_wrap=4)
    
    
    

    enter image description here

    expected structure or df

    • 13 columns, last column indicating the status
    c1 c2 c3 c4 c5 c6 c7 c8 c9 c10 c11 c12 status
    10 7 3 1 7 2 8 1 3 9 6 3 8 1
    11 4 5 8 9 5 4 3 6 3 7 4 8 1
    12 6 3 2 6 5 6 4 3 5 3 9 7 1
    13 4 2 4 8 6 3 3 5 8 8 1 4 1
    14 4 9 9 3 1 8 2 5 1 5 1 4 1
    15 4 9 6 2 9 4 1 6 6 1 6 1 0
    16 8 5 9 7 7 3 1 1 2 5 2 9 0
    17 6 1 4 2 8 5 9 8 2 4 8 4 0
    18 1 6 1 3 8 5 5 9 8 9 2 9 0
    19 1 4 1 1 7 8 2 3 5 6 6 4 0