Search code examples
pythonplotlyplotly-dash

Plotly: Color bars in barchart according to row value


I am making a barchart in Plotly that is built from a specific dataframe row. The data in the columns ranges from -1 to 1 and so I would like to color the bars depending on positive/negative values. Any idea how to do this?

import pandas as pd
import plotly.express as px

fig = px.bar(df.iloc[1])
fig.show()

The data for df.iloc[0] looks like this:

RevolvingUtilizationOfUnsecuredLines    0.612380
age                                     0.142217
NumberOfTime30-59DaysPastDueNotWorse   -0.330435
DebtRatio                              -0.246493
MonthlyIncome                           0.338708
NumberOfOpenCreditLinesAndLoans        -0.213658
NumberOfTimes90DaysLate                -0.342467
NumberRealEstateLoansOrLines            0.131937
NumberOfTime60-89DaysPastDueNotWorse   -0.196677
NumberOfDependents                      0.015418
MonthlyIncomePerPerson                 -0.100884
isRetired                               0.016656
Q1_Monthly_Income_True                 -0.079412
Q3_Monthly_Income_True                  0.000109
Q1_Revolving_True                       0.023684
Q3_Revolving_True                       0.273972

Solution

    • an approach is to reshape a row of your dataframe (a series) into a dataframe
    df.iloc[1].T.to_frame().reset_index().rename(columns={0: "x", 1: "y"}),
    
    • it then becomes simple to use Plotly Express to do formatting you want
    px.bar(
        df.iloc[1].T.to_frame().reset_index().rename(columns={0: "x", 1: "y"}),
        x="x",
        y="y",
        color="y",
        range_color=[-1, 1],
    )
    
    • it is also possible to manually do this configuration
    fig = px.bar(df.iloc[1])
    fig.for_each_trace(
        lambda t: t.update(marker_color=t.y, marker_coloraxis="coloraxis")
    ).update_layout(
        coloraxis_cmin=-1,
        coloraxis_cmax=1,
        coloraxis_colorscale=px.colors.sequential.Viridis,
        showlegend=False
    )
    

    full code as MWE

    import io
    import pandas as pd
    import plotly.express as px
    import plotly.colors
    
    # reconstruct dataframe
    df = (
        pd.read_csv(
            io.StringIO(
                """RevolvingUtilizationOfUnsecuredLines    0.612380
    age                                     0.142217
    NumberOfTime30-59DaysPastDueNotWorse   -0.330435
    DebtRatio                              -0.246493
    MonthlyIncome                           0.338708
    NumberOfOpenCreditLinesAndLoans        -0.213658
    NumberOfTimes90DaysLate                -0.342467
    NumberRealEstateLoansOrLines            0.131937
    NumberOfTime60-89DaysPastDueNotWorse   -0.196677
    NumberOfDependents                      0.015418
    MonthlyIncomePerPerson                 -0.100884
    isRetired                               0.016656
    Q1_Monthly_Income_True                 -0.079412
    Q3_Monthly_Income_True                  0.000109
    Q1_Revolving_True                       0.023684
    Q3_Revolving_True                       0.273972"""
            ),
            sep="\s+",
            header=None,
        )
        .set_index(0)
        .T
    )
    df = pd.concat([df, df])
    df.iloc[1]
    
    # question code
    fig = px.bar(df.iloc[1])
    fig.show()
    
    # solution
    px.bar(
        df.iloc[1].T.to_frame().reset_index().rename(columns={0: "x", 1: "y"}),
        x="x",
        y="y",
        color="y",
        range_color=[-1, 1],
    )
    

    enter image description here