Search code examples
plotlyplotly-python

Side by side plot display for different traces in plotly


This is a snippet of my dataframe:

api_group   commit_date type_of_change  count
Other           2015    Non-Breaking    23
Mature          2016    Non-Breaking    96
Developing      2022    Breaking        2
Legacy          2022    Non-Breaking    3
Other           2019    Non-Breaking    148
Legacy          2018    Non-Breaking    5
Early           2019    Breaking        1793
Legacy          2021    Non-Breaking    12
Early           2016    Breaking        711
Mature          2022    Non-Breaking    30

I am trying to plot this graph:

import pandas as pd
import plotly.graph_objs as go

new['commit_date'] = pd.to_datetime(new['commit_date'])

df_grouped = new.groupby([new['api_group'], new['commit_date'].dt.year, 'type_of_change'])['type_of_change'].count().reset_index(name='count')

figs = []
for api_group in df_grouped['api_group'].unique():
    breaking_pivot = df_grouped[df_grouped['api_group'] == api_group].pivot_table(index='commit_date', columns='type_of_change', values='count', fill_value=0)

    fig = go.Figure()
    
    fig.add_trace(go.Scatter(x=breaking_pivot.index, y=breaking_pivot['Breaking'], name='Breaking', line=dict(dash='solid'), line_width=2.5))
    fig.add_trace(go.Scatter(x=breaking_pivot.index, y=breaking_pivot['Non-Breaking'], name='Non-Breaking', line=dict(dash='dot'), line_width=2.5))

    fig.update_layout(title=f'Evolution of Breaking Changes Over Time for {api_group}', width=600, height=500, template='ggplot2', xaxis_title='Year', yaxis_title='Number of Releases')
    
    figs.append(fig)

for fig in figs:
    fig.show()

For every api_group, it displays the breaking and non breaking changes in it, but the issue is it plots all the graphs for all the 5 groups in a line, but I want them displayed side by side. The graph is this: enter image description here

Is there a way I could do this, because I am not sure how to plot multiple traces using subplot function in plotly.


Solution

  • I slightly changed your data to have a better example

    Data

    import pandas as pd
    import plotly.express as px
    
    data = [['Developing', 2022, 'Breaking', 2],
           ['Early', 2016, 'Breaking', 711],
           ['Early', 2019, 'Breaking', 1793],
           ['Legacy', 2018, 'Non-Breaking', 5],
           ['Legacy', 2021, 'Non-Breaking', 12],
           ['Legacy', 2022, 'Non-Breaking', 3],
           ['Mature', 2016, 'Non-Breaking', 96],
           ['Mature', 2022, 'Non-Breaking', 30],
           ['Other', 2015, 'Non-Breaking', 23],
           ['Other', 2019, 'Non-Breaking', 148],
           ['Other', 2017, 'Breaking', 15],
           ['Other', 2019, 'Breaking', 5]]
    
    df = pd.DataFrame(
            data, 
            columns=[
                'api_group',
                'commit_date',
                'type_of_change',
                'count'])
    

    Now ou want to be sure data is correclty ordered

    df = df.sort_values(
        ["api_group",
         "type_of_change",
         "commit_date"])\
        .reset_index(drop=True)
    

    Plot

    # here we leverage plotly express for
    # subplots
    fig = px.line(
        df,
        x="commit_date",
        y="count",
        facet_col="api_group",
        color="type_of_change")
    
    # here I change to `dot` in case we are plotting
    # 'Non-Breaking'
    for d in fig.data:
        if d["legendgroup"] == 'Non-Breaking':
            d["line"]["dash"] = "dot"
    
    fig.show()
    

    enter image description here