Search code examples
pythonplotgraphplotly

How to make a customized graph from a dataframe using python


I'm trying to draw a specific graph from the dataframe shown below :

      Type   Test  Speed  Efficiency  Durability
0  Model A     OK      3           3           3
1  Model A  nonOK      2           2           2
2  Model B     OK      1           1           2
3  Model B  nonOK      3           3           2
4  Model C     OK      3           2           6
5  Model C  nonOK      3           4           0

This is the expected graph output :

enter image description here

I tried something very basic with plotly express but I got a different output :

fig = px.bar(df, x="Type", y=['Speed', 'Efficiency', 'Durability'],
            color="Test", height=450, width=500)

fig.show()

enter image description here

Do you have any suggestions please ?


Solution

  • plotly express has facet plots link to docu
    Kudos to this answer from Saaru Lindestøkke from where I got this info.

    Figure result (code see below): enter image description here


    Dataframe needs to be reshaped from wide to long, e.g. with melt:

    import pandas as pd
    import io
    
    data_provided = '''                  
       Type,   Test,  Speed,  Efficiency,  Durability
    Model A,     OK,      3,           3,           3
    Model A,  nonOK,      2,           2,           2
    Model B,     OK,      1,           1,           2
    Model B,  nonOK,      3,           3,           2
    Model C,     OK,      3,           2,           6
    Model C,  nonOK,      3,           4,           0
    '''
    df_fromstring = pd.read_csv(io.StringIO(data_provided), skipinitialspace=True)
    
    df_long = pd.melt(df_fromstring, id_vars=['Type', 'Test'], 
                      value_vars=['Speed', 'Efficiency', 'Durability'],
                      var_name='Characteristics', value_name='amount')
    
    print(df_long)
    
           Type   Test Characteristics  amount
    0   Model A     OK           Speed       3
    1   Model A  nonOK           Speed       2
    2   Model B     OK           Speed       1
    3   Model B  nonOK           Speed       3
    4   Model C     OK           Speed       3
    5   Model C  nonOK           Speed       3
    6   Model A     OK      Efficiency       3
    7   Model A  nonOK      Efficiency       2
    8   Model B     OK      Efficiency       1
    9   Model B  nonOK      Efficiency       3
    10  Model C     OK      Efficiency       2
    11  Model C  nonOK      Efficiency       4
    12  Model A     OK      Durability       3
    13  Model A  nonOK      Durability       2
    14  Model B     OK      Durability       2
    15  Model B  nonOK      Durability       2
    16  Model C     OK      Durability       6
    17  Model C  nonOK      Durability       0
    

    Stacked and grouped bar plot:

    import plotly.express as px
    
    fig = px.bar(df_long, x="Characteristics", y="amount", facet_col="Type", color="Test",
                 text_auto=True)  # text_auto=True to print the values inside the bars
    
    fig.show()
    

    Note: Figure result was posted on top.


    Add-on 1: Some example to change the plot title and axis (no plot picture added, give it a try):

    import plotly.graph_objects as go
    
    fig = px.bar(df_long, x="Characteristics", y="amount", facet_col="Type", color="Test", 
                 title="Some Title", text_auto=True)  
    
    # remove x axis subplots titles (bottom)
    for axis in fig.layout:
        if type(fig.layout[axis]) == go.layout.XAxis:
            fig.layout[axis].title.text = ''   
    
    # set some new figure titels 
    fig.update_layout(title = "Some Other Title", title_x=0.5,
         xaxis_title = 'Type', yaxis_title = 'Value')
        
    fig.show()
    

    Add-on 2: Plotly Static Image Export in Python (just mentioned as I had to look that up as well):

    Required - if not installed already:

    $ pip install -U kaleido
    or
    $ conda install -c conda-forge python-kaleido

    fig.write_image("Plotly_Bar_Stacked_Grouped.png")