{"spec_id":"box-basic","library":"plotly","language":"python","code":"\"\"\" anyplot.ai\nbox-basic: Basic Box Plot\nLibrary: plotly 6.7.0 | Python 3.13.13\nQuality: 88/100 | Updated: 2026-05-28\n\"\"\"\n\nimport os\n\nimport numpy as np\nimport plotly.graph_objects as go\n\n\n# Theme\nTHEME = os.getenv(\"ANYPLOT_THEME\", \"light\")\nPAGE_BG = \"#FAF8F1\" if THEME == \"light\" else \"#1A1A17\"\nELEVATED_BG = \"#FFFDF6\" if THEME == \"light\" else \"#242420\"\nINK = \"#1A1A17\" if THEME == \"light\" else \"#F0EFE8\"\nINK_SOFT = \"#4A4A44\" if THEME == \"light\" else \"#B8B7B0\"\nGRID = \"rgba(26,26,23,0.15)\" if THEME == \"light\" else \"rgba(240,239,232,0.15)\"\nLEGEND_BORDER = \"rgba(74,74,68,0.3)\" if THEME == \"light\" else \"rgba(184,183,176,0.3)\"\n\nIMPRINT_PALETTE = [\"#009E73\", \"#C475FD\", \"#4467A3\", \"#BD8233\", \"#AE3030\", \"#2ABCCD\", \"#954477\", \"#99B314\"]\n\n# Data\nnp.random.seed(42)\ncategories = [\"Engineering\", \"Marketing\", \"Sales\", \"HR\", \"Finance\"]\ncolors = IMPRINT_PALETTE[:5]\n\ndata = {\n    \"Engineering\": np.random.normal(95000, 15000, 100),\n    \"Marketing\": np.random.normal(75000, 12000, 80),\n    \"Sales\": np.random.normal(70000, 20000, 120),\n    \"HR\": np.random.normal(65000, 10000, 60),\n    \"Finance\": np.random.normal(85000, 14000, 90),\n}\ndata = {k: np.clip(v, 25000, None) for k, v in data.items()}\n\nmedians = {k: float(np.median(v)) for k, v in data.items()}\nhighest_dept = max(medians, key=medians.get)\nlowest_dept = min(medians, key=medians.get)\n\n# Plot\nfig = go.Figure()\n\n# Market rate band — PNG-visible plotly shape highlighting target compensation range\nfig.add_hrect(\n    y0=75000,\n    y1=90000,\n    fillcolor=IMPRINT_PALETTE[0],\n    opacity=0.06,\n    line_width=0,\n    layer=\"below\",\n    annotation_text=\"Market rate band\",\n    annotation_position=\"top right\",\n    annotation_font_size=9,\n    annotation_font_color=INK_SOFT,\n)\n\nfor i, category in enumerate(categories):\n    values = data[category]\n    fig.add_trace(\n        go.Box(\n            y=values,\n            name=category,\n            marker_color=colors[i],\n            fillcolor=colors[i],\n            opacity=0.85,\n            boxpoints=\"outliers\",\n            marker={\"size\": 10, \"opacity\": 0.8, \"line\": {\"width\": 1, \"color\": INK_SOFT}},\n            line={\"width\": 2.5, \"color\": colors[i]},\n            whiskerwidth=0.6,\n            hovertemplate=\"<b>%{x}</b><br>Salary: $%{y:,.0f}<br><extra></extra>\",\n        )\n    )\n\n# Annotations\nhighest_color = colors[categories.index(highest_dept)]\nlowest_color = colors[categories.index(lowest_dept)]\n\nfig.add_annotation(\n    x=highest_dept,\n    y=medians[highest_dept],\n    text=f\"Highest median<br><b>${medians[highest_dept]:,.0f}</b>\",\n    showarrow=True,\n    arrowhead=2,\n    arrowsize=1.2,\n    arrowwidth=2,\n    arrowcolor=highest_color,\n    ax=70,\n    ay=-60,\n    font={\"size\": 11, \"color\": highest_color},\n    bordercolor=highest_color,\n    borderwidth=1.5,\n    borderpad=6,\n    bgcolor=ELEVATED_BG,\n)\n\nfig.add_annotation(\n    x=lowest_dept,\n    y=medians[lowest_dept],\n    text=f\"Lowest median<br><b>${medians[lowest_dept]:,.0f}</b>\",\n    showarrow=True,\n    arrowhead=2,\n    arrowsize=1.2,\n    arrowwidth=2,\n    arrowcolor=lowest_color,\n    ax=80,\n    ay=-60,\n    font={\"size\": 11, \"color\": lowest_color},\n    bordercolor=lowest_color,\n    borderwidth=1.5,\n    borderpad=6,\n    bgcolor=ELEVATED_BG,\n)\n\ngap = medians[highest_dept] - medians[lowest_dept]\nfig.add_annotation(\n    x=0.98,\n    y=0.98,\n    xref=\"paper\",\n    yref=\"paper\",\n    text=f\"Median salary gap: <b>${gap:,.0f}</b>\",\n    showarrow=False,\n    font={\"size\": 11, \"color\": INK_SOFT},\n    bordercolor=INK_SOFT,\n    borderwidth=1,\n    borderpad=8,\n    bgcolor=ELEVATED_BG,\n    xanchor=\"right\",\n    yanchor=\"top\",\n)\n\ntitle_text = \"box-basic · python · plotly · anyplot.ai\"\n\nfig.update_layout(\n    autosize=False,\n    title={\n        \"text\": f\"<b>{title_text}</b><br><span style='font-size:11px;color:{INK_SOFT}'>Annual Salary Distribution Across Departments</span>\",\n        \"font\": {\"size\": 16, \"color\": INK},\n        \"x\": 0.5,\n        \"xanchor\": \"center\",\n    },\n    xaxis={\n        \"tickfont\": {\"size\": 11, \"color\": INK_SOFT},\n        \"showline\": True,\n        \"linewidth\": 1.5,\n        \"linecolor\": INK_SOFT,\n        \"zeroline\": False,\n        \"showgrid\": False,\n    },\n    yaxis={\n        \"title\": {\"text\": \"Annual Salary ($)\", \"font\": {\"size\": 12, \"color\": INK}, \"standoff\": 10},\n        \"tickfont\": {\"size\": 10, \"color\": INK_SOFT},\n        \"tickformat\": \"$,.0f\",\n        \"gridcolor\": GRID,\n        \"gridwidth\": 1,\n        \"zeroline\": False,\n        \"showline\": True,\n        \"linewidth\": 1.5,\n        \"linecolor\": INK_SOFT,\n        \"range\": [20000, 155000],\n        \"dtick\": 20000,\n        \"showgrid\": True,\n    },\n    showlegend=True,\n    legend={\n        \"bgcolor\": ELEVATED_BG,\n        \"bordercolor\": LEGEND_BORDER,\n        \"borderwidth\": 1,\n        \"font\": {\"size\": 10, \"color\": INK_SOFT},\n        \"orientation\": \"h\",\n        \"yanchor\": \"bottom\",\n        \"y\": -0.25,\n        \"xanchor\": \"center\",\n        \"x\": 0.5,\n    },\n    paper_bgcolor=PAGE_BG,\n    plot_bgcolor=PAGE_BG,\n    font={\"color\": INK},\n    margin={\"l\": 80, \"r\": 40, \"t\": 100, \"b\": 110},\n)\n\n# Save\nfig.write_image(f\"plot-{THEME}.png\", width=800, height=450, scale=4)\nfig.write_html(f\"plot-{THEME}.html\", include_plotlyjs=\"cdn\")\n"}