{"spec_id":"confusion-matrix","library":"altair","language":"python","code":"\"\"\" anyplot.ai\nconfusion-matrix: Confusion Matrix Heatmap\nLibrary: altair 6.1.0 | Python 3.13.13\nQuality: 72/100 | Updated: 2026-05-09\n\"\"\"\n\nimport altair as alt\nimport numpy as np\nimport pandas as pd\n\n\n# Data - Multi-class classification results\nnp.random.seed(42)\nclass_names = [\"Dog\", \"Cat\", \"Bird\", \"Fish\"]\nn_classes = len(class_names)\n\n# Create a realistic confusion matrix with clear patterns\n# Most predictions on diagonal (correct), some off-diagonal (errors)\nconfusion = np.array(\n    [\n        [85, 10, 3, 2],  # Dogs: mostly correct, some confused with cats\n        [12, 78, 6, 4],  # Cats: mostly correct, some confused with dogs\n        [5, 8, 82, 5],  # Birds: mostly correct, some confusion\n        [2, 4, 3, 91],  # Fish: very distinct, high accuracy\n    ]\n)\n\n# Create long-form DataFrame for Altair\nrows = []\nfor i, true_class in enumerate(class_names):\n    for j, pred_class in enumerate(class_names):\n        rows.append(\n            {\n                \"True Label\": true_class,\n                \"Predicted Label\": pred_class,\n                \"Count\": confusion[i, j],\n            }\n        )\n\ndf = pd.DataFrame(rows)\n\n# Base heatmap with rectangles\nbase = alt.Chart(df).encode(\n    x=alt.X(\"Predicted Label:N\", sort=class_names, axis=alt.Axis(labelAngle=0, labelFontSize=20, titleFontSize=24)),\n    y=alt.Y(\"True Label:N\", sort=class_names, axis=alt.Axis(labelFontSize=20, titleFontSize=24)),\n)\n\n# Heatmap cells\nheatmap = base.mark_rect(stroke=\"white\", strokeWidth=2).encode(\n    color=alt.Color(\n        \"Count:Q\",\n        scale=alt.Scale(scheme=\"blues\"),\n        legend=alt.Legend(title=\"Count\", titleFontSize=18, labelFontSize=16, gradientLength=300, gradientThickness=25),\n    )\n)\n\n# Text annotations - white on dark cells, dark on light cells\ntext = base.mark_text(fontSize=28, fontWeight=\"bold\").encode(\n    text=\"Count:Q\", color=alt.condition(alt.datum.Count > 50, alt.value(\"white\"), alt.value(\"#306998\"))\n)\n\n# Combine heatmap and text\nchart = (\n    (heatmap + text)\n    .properties(\n        width=1000,\n        height=1000,\n        title=alt.Title(\"confusion-matrix · altair · pyplots.ai\", fontSize=32, anchor=\"middle\", offset=20),\n    )\n    .configure_view(strokeWidth=0)\n    .configure_axis(domainWidth=0)\n)\n\n# Save as PNG (1000 * 3.6 = 3600 for square format)\nchart.save(\"plot.png\", scale_factor=3.6)\n\n# Save interactive HTML version\nchart.save(\"plot.html\")\n"}