Search code examples
pythonplotly-python

Why am I unable to make a plot containing subplots in plotly using a px.scatter plot?


I have been trying to make a figure using plotly that combines multiple figures together. In order to do this, I have been trying to use the make_subplots function, but I have found it very difficult to have the plots added in such a way that they are properly formatted. I can currently make singular plots (as seen directly below): single plot example

However, whenever I try to combine these singular plots using make_subplots, I end up with this: multiple plot example

This figure has the subplots set up completely wrong, since I need each of the four subplots to contain data pertaining to the four methods (A, B, C, and D). In other words, I would like to have four subplots that look like my singular plot example above.

I have set up the code in the following way:

for sequence in sequences:
    #process for making sequence profile is done here
    sequence_df = pd.DataFrame(sequence_profile)
    row_number=1
    grand_figure = make_subplots(rows=4, cols=1)
    #there are four groups per sequence, so the grand figure should have four subplots in total
    for group in sequence_df["group"].unique():
        figure_df_group = sequence_df[(sequence_df["group"]==group)] 
        figure_df_group.sort_values("sample", ascending=True, inplace=True)
        figure = px.line(figure_df_group, x = figure_df_group["sample"], y = figure_df_group["intensity"], color= figure_df_group["method"])
        figure.update_xaxes(title= "sample")
        figure.update_traces(mode='markers+lines')
        #note: the next line fails, since data must be extracted from the figure, hence why it is commented out 
        #grand_figure.append_trace(figure, row = row_number, col=1)
        figure.update_layout(title_text="{} Profile Plot".format(sequence))
        grand_figure.append_trace(figure.data[0], row = row_number, col=1)
        row_number+=1
        figure.write_image(os.path.join(output_directory+"{}_profile_plot_subplots_in_{}.jpg".format(sequence, group)))     
    grand_figure.write_image(os.path.join(output_directory+"grand_figure_{}_profile_plot_subplots.jpg".format(sequence)))

I have tried following directions (like for example, here: ValueError: Invalid element(s) received for the 'data' property) but I was unable to get my figures added as is as subplots. At first it seemed like I needed to use the graph object (go) module in plotly (https://plotly.com/python/subplots/), but I would really like to keep the formatting/design of my current singular plot. I just want the plots to be conglomerated in groups of four. However, when I try to add the subplots like I currently do, I need to use the data property of the figure, which causes the design of my scatter plot to be completely messed up. Any help for how I can ameliorate this problem would be great.


Solution

  • Ok, so I found a solution here. Rather than using the make_subplots function, I just instead exported all the figures onto an .html file (Plotly saving multiple plots into a single html) and then converted it into an image (HTML to IMAGE using Python). This isn't exactly the approach I would have preferred to have, but it does work.

    UPDATE

    I have found that plotly express offers another solution, as the px.line object has the parameter of facet that allows one to set up multiple subplots within their plot. My code is set up like this, and is different from the code above in that the dataframe does not need to be iterated in a for loop based on its groups:

    sequence_df = pd.DataFrame(sequence_profile)        
    figure = px.line(sequence_df, x = sequence_df["sample"], y = sequence_df["intensity"], color= sequence_df["method"], facet_col= sequence_df["group"])
    

    Although it still needs more formatting, my plot now looks like this, which is works much better for my purposes:

    faceted plot example