Diverging Bar Chart — Plotly

A diverging bar chart displays bars extending in opposite directions from a central baseline, typically at zero. This visualization is ideal for comparing positive and negative values, showing responses above and below a neutral point, or contrasting opposing categories. Different colors distinguish positive from negative values, making it easy to identify magnitude and direction at a glance.

Diverging Bar Chart rendered with Plotly

Renders

Python source (Plotly)

""" anyplot.ai
bar-diverging: Diverging Bar Chart
Library: plotly 6.9.0 | Python 3.13.15
Quality: 94/100 | Updated: 2026-08-18
"""

import os

import plotly.graph_objects as go


# Theme tokens
THEME = os.getenv("ANYPLOT_THEME", "light")
PAGE_BG = "#FAF8F1" if THEME == "light" else "#1A1A17"
ELEVATED_BG = "#FFFDF6" if THEME == "light" else "#242420"
INK = "#1A1A17" if THEME == "light" else "#F0EFE8"
INK_SOFT = "#4A4A44" if THEME == "light" else "#B8B7B0"
GRID = "rgba(26,26,23,0.15)" if THEME == "light" else "rgba(240,239,232,0.15)"

# Imprint palette: position 1 (brand green) for positive, position 5 (matte
# red) for negative — sentiment/polarity semantic exception
POSITIVE_COLOR = "#009E73"
NEGATIVE_COLOR = "#AE3030"

# Data: Customer satisfaction survey results by department
# Scores range from -100 (very dissatisfied) to +100 (very satisfied)
categories = [
    "Customer Support",
    "Product Quality",
    "Delivery Speed",
    "Website Experience",
    "Return Policy",
    "Price Value",
    "Mobile App",
    "Payment Options",
    "Product Variety",
    "Checkout Process",
]
values = [72, 58, -25, 45, -42, 31, -15, 68, 22, -8]

# Sort by value for better pattern recognition
sorted_data = sorted(zip(categories, values, strict=True), key=lambda x: x[1])
categories_sorted = [item[0] for item in sorted_data]
values_sorted = [item[1] for item in sorted_data]

# Assign colors: Imprint brand green for positive, matte red for negative
colors = [POSITIVE_COLOR if v >= 0 else NEGATIVE_COLOR for v in values_sorted]

# Redundant non-color encoding beyond bar direction + sign: a diagonal hatch
# flags negative bars, distinctive Plotly marker.pattern usage
patterns = ["" if v >= 0 else "/" for v in values_sorted]

# The two extreme bars (sorted ascending, so index 0 and -1) get a bolder
# outline to draw the eye to the highest/lowest departments
extreme_indices = {0, len(values_sorted) - 1}
line_widths = [2.5 if i in extreme_indices else 1 for i in range(len(values_sorted))]
line_colors = [INK if i in extreme_indices else PAGE_BG for i in range(len(values_sorted))]

# Net sentiment context for the subtitle and richer hover cards
net_avg = sum(values_sorted) / len(values_sorted)
bottom_cat, bottom_val = sorted_data[0]
top_cat, top_val = sorted_data[-1]
sentiment_labels = ["Positive" if v >= 0 else "Negative" for v in values_sorted]
customdata = list(zip(sentiment_labels, [abs(v) for v in values_sorted], strict=True))

# Create horizontal diverging bar chart
fig = go.Figure()

fig.add_trace(
    go.Bar(
        y=categories_sorted,
        x=values_sorted,
        orientation="h",
        marker={
            "color": colors,
            "line": {"color": line_colors, "width": line_widths},
            "pattern": {"shape": patterns, "fgcolor": PAGE_BG, "size": 6, "solidity": 0.25},
        },
        text=[f"{v:+d}" for v in values_sorted],
        textposition="outside",
        textfont={"size": 12, "color": colors},
        customdata=customdata,
        hovertemplate=(
            "<b>%{y}</b><br>Score: %{x:+d}<br>Sentiment: %{customdata[0]}<br>"
            "Magnitude: %{customdata[1]} of 100<extra></extra>"
        ),
    )
)

# Add zero baseline
fig.add_vline(x=0, line={"color": INK_SOFT, "width": 2})

# Layout styling for 3200x1800
fig.update_layout(
    autosize=False,
    title={
        "text": (
            "bar-diverging · python · plotly · anyplot.ai<br>"
            f"<span style='font-size:13px;font-weight:normal;color:{INK_SOFT}'>"
            f"Net sentiment {net_avg:+.0f} avg · {top_cat} leads ({top_val:+d}) · "
            f"{bottom_cat} trails ({bottom_val:+d})</span>"
        ),
        "font": {"size": 20, "color": INK},
        "x": 0.5,
        "xanchor": "center",
    },
    xaxis={
        "title": {"text": "Satisfaction Score (-100 to +100)", "font": {"size": 16, "color": INK}},
        "tickfont": {"size": 13, "color": INK_SOFT},
        "range": [-100, 100],
        "dtick": 25,
        "gridcolor": GRID,
        "linecolor": INK_SOFT,
        "zeroline": False,
    },
    yaxis={
        "title": {"text": "Department", "font": {"size": 16, "color": INK}},
        "tickfont": {"size": 13, "color": INK_SOFT},
        "automargin": True,
        "linecolor": INK_SOFT,
    },
    paper_bgcolor=PAGE_BG,
    plot_bgcolor=PAGE_BG,
    showlegend=False,
    margin={"l": 20, "r": 60, "t": 110, "b": 70},
    bargap=0.3,
)

# Save outputs
fig.write_image(f"plot-{THEME}.png", width=800, height=450, scale=4)
fig.write_html(f"plot-{THEME}.html", include_plotlyjs="cdn")

Retrieve this implementation

Runnable source as JSON, for any HTTP client: https://api.anyplot.ai/specs/bar-diverging/plotly/code. Any spec id and library id listed in llms-full.txt fit the same URL shape; every URL below is complete and callable.

{
  "spec_id": "bar-diverging",
  "language": "python",
  "library": "plotly",
  "page": "https://anyplot.ai/bar-diverging/python/plotly",
  "hub": "https://anyplot.ai/bar-diverging",
  "code_json": "https://api.anyplot.ai/specs/bar-diverging/plotly/code",
  "spec_json": "https://api.anyplot.ai/specs/bar-diverging",
  "render_light_png": "https://storage.googleapis.com/anyplot-images/plots/bar-diverging/python/plotly/plot-light.png",
  "render_dark_png": "https://storage.googleapis.com/anyplot-images/plots/bar-diverging/python/plotly/plot-dark.png",
  "interactive_light_html": "https://storage.googleapis.com/anyplot-images/plots/bar-diverging/python/plotly/plot-light.html",
  "interactive_dark_html": "https://storage.googleapis.com/anyplot-images/plots/bar-diverging/python/plotly/plot-dark.html",
  "quality_score": 94.0,
  "license": "MIT",
  "guide": "https://anyplot.ai/llms.txt"
}

Part of Diverging Bar Chart on anyplot.ai.

Other implementations