{ "cells": [ { "cell_type": "markdown", "id": "5610fac1", "metadata": {}, "source": [ "# GoldenViz examples: 25 rules\n", "\n", "Each example is a complete, standalone Matplotlib snippet. The good-chart code highlights the lines that were added or corrected." ] }, { "cell_type": "markdown", "id": "7b34f42f", "metadata": {}, "source": [ "" ] }, { "cell_type": "markdown", "id": "80c8cea4", "metadata": {}, "source": [ "## Installation check output\n", "\n", "This cell reproduces the installation smoke test. The first output is the Matplotlib chart; the second output is the GoldenViz report embedded as HTML." ] }, { "cell_type": "code", "execution_count": 1, "id": "bfde84e9", "metadata": { "execution": { "iopub.execute_input": "2026-06-16T17:54:23.605810Z", "iopub.status.busy": "2026-06-16T17:54:23.605558Z", "iopub.status.idle": "2026-06-16T17:54:24.463753Z", "shell.execute_reply": "2026-06-16T17:54:24.462838Z" } }, "outputs": [ { "data": { "image/png": "iVBORw0KGgoAAAANSUhEUgAAA6oAAAHoCAYAAABAcxJQAAAAOnRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjEwLjgsIGh0dHBzOi8vbWF0cGxvdGxpYi5vcmcvwVt1zgAAAAlwSFlzAAAYmwAAGJsBSXWDlAAAe3pJREFUeJzt3Qd4VFX6+PE3PaRDAiGk05EeqQmKYgOxgGADqbK76rqufV3LWtfVtS3q6rquVEUWUVREVFAUSSCUANJBSCeVkkrqzP85Z3+Tf5KZhIRMMpPM9/M8Y8Lcc+eeOXNzve+cc97jZDQajQIAAAAAgJ1wtnUFAAAAAACojUAVAAAAAGBXCFQBAAAAAHaFQBUAAAAAYFcIVAEAAAAAdoVAFQAAAABgVwhUAQAAAAB2hUAVAAAAAGBXCFQBAAAAAHaFQBUAAAAAYFcIVAEAAAAAdoVAFQAAAABgVwhUAQAAAAB2hUAVAAAAAGBXCFQBAAAAAHaFQBUAbGDJkiXi5ORk9nB2dhZ/f38ZPHiw3HXXXZKUlMTng3bvsssu0+f33Llzm71vSkpKzd/Hjz/+2Cr1AwDYHwJVALAjRqNRCgsLZf/+/fLee+/JyJEj5fnnn7d1tWDFLyYAAMD5EagCgI19/fXXUlRUpB9nzpzRvajPPvuseHp6isFgkL/85S/y2Wef2bqaAAAAbYZAFQBsrFOnTuLj46MfAQEBMnz4cB2cfvjhhzVlXnnlFZvWEQAAoC0RqAKAnZo2bZr06dNH/75jxw6pqKiwdZUAAADaBIEqANixAQMG6J/V1dVy+vTpBsupJDOzZs2S6Oho3UPr5+cnw4YN0z2zajhxfe+//37NnMkTJ040Wofjx4/XlH333XctltmzZ4/89re/lb59++qeYW9vb7nooovkwQcflMzMzAZfOyoqSr/uM888o//95ZdfytVXXy1du3bVQ5/79esnTzzxhJ6329D7NtVNJd1piHp9VUYdrzHNbcemJgKaN29ezXOWkmjVZnpOzWtVQ7//9a9/ySWXXKLbRCXbMrWViTo3li1bJpMnT5aQkBBxd3eXwMBAncDo3//+t1RVVTWp7UpKSuS5556TQYMG6c9PJfVSr7F69erzvk/1Gd9zzz26fdXn1qNHD/1FS3x8vFjbuXPn5K9//asMGTJEfH199SiESy+9VD766COL5efPn6/fY2hoqG6rxixfvrymTQ4ePNik+qi2N+1z+PDhRsumpaWJi4uLLvvOO+9Y9W+prKxMTyO4++67dduoc9fNzU26desmV155pf6bb+zLLpXoStVLfeZKYmKizJw5UyIiIvQ5db6/HQCwOiMAoM0tXrzYqC7B6rFp06YGy1133XU15UpLS822l5WVGWfNmlVTxtIjODjYuGPHjjr7nTlzxujh4aG3P/vss43W9ZlnntHl3N3djadOnaqzzWAwGB999FGjk5NTg8f38fExfv311xZfOzIyUpd5+umnjffff3+DrzF06FBjUVGR2f6q7UxlkpOTG3wP6vVVGXU8Sy60Hc9H1amx1zQ9ajM9969//cs4YcIEs7LqvZikp6cbY2JiGn3t0aNHG/Py8hptu61btxoHDBjQ4Gs8//zzDb5Hta+/v7/F/VxcXIz//ve/jePHj9f/njNnTrPar34brlmzxjhkyJAG63nbbbcZq6qq6uwfHx9fs33dunWNHuvyyy+vabOmUn+Xpvf/yCOPNFpW/a2pcp6envpv0Jp/S439/ZgeY8aMMTuuifpsVBn1WalzT312tfdt6G8HAFoLgSoA2HGg2rt3b12mV69eFrffeuuterurq6vxj3/8ozExMdGYn59vPHnypHHVqlXG/v371wRZWVlZdfadPn263ta3b99G69qnTx9dburUqWbb/vSnP+lt6uZ69uzZxp9++smYm5urH+qGWt3wq+1eXl7G/fv3Nxio9uzZU//8zW9+o4NBFRAfOnTIeNddd9W005///OdWC1Rb0o6NUcGHCrDVjb+pnurf9R+1mcqFhYUZnZ2djQ888IBxz549uj579+41bt++XZcrKCio+WyCgoKMr732mvHAgQPG06dPG48fP25cuHBhTQClArDq6uoG2061v3qNt99+23jixAl9rI0bNxoHDRpUE3AePHjQ7P2pz1ntp8p4e3sbX3nlFb2/6fMfNmyY/oIjNDTUKoFqdHS00c3Nzfjkk08aDx8+rOupzrnaAf0TTzxh9hoXXXSR3jZt2rQGj6PqbQoSVXDdHHfffbfer3v37sbKysoGzwVVf1VuxowZVv9bUuf4nXfeaVy5cqX+G1JfYuTk5Bh37dpl/Mtf/mLs3LlzTTDfWKCqznH1dzB27Fjj+vXr9WukpaUZv/zyy2a1CQC0FIEqANhpoKoCJFOZN954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vPXWW41XXXWV0c/PTz+vrgu7d+9udttzbW/7dufabptznWt727c71/bzX9s3/N//g9T/59RnMH36dOOUKVP0/0NM5+zLL7/cbq7tzUWgaiXff/+9vhHavHmz2baVK1fqm2P1AS5durTOtqSkJH1CqO1ff/11zfMlJSXGK664ouYGq74JEyYYP/jgA2NRUVGd55OTk40DBw7U+6mbm/qKi4v1/wRfffVV4w8//GDcs2ePVW7eb7zxRv06qs6q7ibr1q3Tr62Cqb1795rt98Ybb+j91M3ZiRMnap5Xv/fo0UNve+uttxo8riO3+x/+8Afjs88+a8zIyKjzvKqburlVr9+lSxfj6dOnG7x5V/VuLkduc8X0P4bm4lxvWbs3JDMzs+aci4+Pt+q53p7OdxU8q3MsPz+/zvO5ubnGyy67TO/Xp08ffZPRHFzb277dubbb5lzn2m6bdm8I1/b/yc7O1l8AWAr+VqxYUXOPffDgwXZxbW8uAtU2cuedd9acELWpbx7U8wsWLDDbJyUlRZ8oavuhQ4eafKyff/655oKbnp7eaFl189PSm/cDBw7UvIaqc0PvXQVPtak/OlPvwocffmi23/Lly/U2deJf6LczHbndG6MuOr6+vvoYqh2tffPuyG1+ITcznOutd66/+OKL+vPo37+/xe2tea7b8/lemypr2k+9RlNxbbdNuzeGa3vrtTnXdvs617m2N436clO1e0M9oO3t2l4fc1TbyPDhw/XP9PT0mucqKipq5jepeYb1qTkAcXFx+vc1a9Y0+1j1j9daTHVTdVV1rs/03tauXavne5ls3bpVsrOz9Vj7adOmme2nnlPzs06ePCmJiYkXVLeO3O6NUXNV1ZwDW9TFUdu8MZzrrWfx4sX655133im20B7O97CwMD33qLn7cW23Tbs3hmt727d5Y7i2t167c21vGlPeDXUv3RGu7fW1PIMOmuTYsWP6Z0hISM1zR48eldLSUv37iBEjLO6nnv/5559l9+7dzT5W/eO1FlPdGnsPSklJia7bRRddVGe/gQMH6kRA9amJ3WqbKqceY8eObXbdOnK7N0ZdWEzJlBqri/ofwenTp6Wqqkp69Ogh48ePl0svvbRFx3aUNn/99dfl119/1Qk4VFIDleggJibGYlnO9dahzhd1DqjkRrNnz260bGuc6+3lfM/Pz5czZ840ez+u7bZp98ZwbW/9NufabvtznWt706xbt042bdqk76FV0siOcG2vj0C1DahvH5YsWaJ/r/0NRHJysv6pskiqjFmWhIeH1ynbFC+99JL+qW6aVYaw1maqm7pZt0RlrFSPwsJCXdZ0wp9vP9P7Vyd7c96/o7R7Yz744AP9Pw510Zg0aVKD5Z577jmz51QGuhUrVkjv3r2bfVxHavOHHnqozr8fe+wxmThxon7/wcHBdbZxrreORYsW6Z/XXXeddOvWrdGy1j7X29P5/uqrr+os2OoGMjY2tsn7cW23Tbs3hmt767c513bbn+tc2y2755579JegKkOw+kJ03759+v8x6ovY5nxe9nptt4Shv61MfXt/xx13SEFBgQwePFh+97vf1UkLrXh7eze4v0r9raiTpSnUTdN///tfcXFxkYULF0pbuND30Rrv35HavSHqwqWW0lCeeuops6BJUenH1Q266hE8d+6cvqCopW7UxWfHjh1y2WWX6SUSmsNR2lwNifn88891j7VqO/U/i7ffflsvf/PNN9/ontWysrI6+3CuW59q008++eS8w35b41xvT+e7Wh5H3UQqr732mh6W1VRc223T7g3h2t66bc613T7Oda7tDVuxYoUsXbpUPv30U3096Nq1q75GWRqGe742trf79gZZZaYrGmSakBwYGGg8cuRInW0fffRRTeashvz73//WZVQK6fPZuHGj0d3dXZd/7bXXmvSpWCPBjMrypl7j/fffb7CMKROYylBm8pvf/EY/pzKzNmTGjBk1yz80hyO0e0MJDUzJY2644QaLS2Y05tSpU8aoqCi9/x//+Mdm7euobV47452/v78+hsqKVxvnuvXbXV1vTEkbLiTLZEvO9fZwviu//PKLMSAgQO+nMsk2F9d227S7JVzb277NTbi2t227c21v2v+/fvrpJ+M111xTk/SoOf8ftMdre0PoUW1Ff/zjH/Uwnc6dO8uGDRukb9++dbabhoSpMeANMS0ArLrgG6MW/L3xxht1Eo+nn35aHnzwQWkrF/o+rPn+HbHdLQ1DvOKKKyQ1NVWuueYaWbVqlZ4/2RxdunSR+++/v2YSfVM5apvXFh0dLfPmzbPYdpzr1mcaGjZnzhzdA9BcF3qut5fz/fDhw3LllVfK2bNn9Xl5IaMOuLbbpt3r49re9m1eG9f2tm13ru1N+//XpZdeKuvXr9ejhlauXCnvvvtuu722N8oq4S7MPPjgg/obBfVN044dOxr8JsqUzruwsNBimQceeEBvVwv8NkStHWhaiuSJJ55o1qdhjV4m08K/6j1bUlBQUPM+9+/fX/O8SqWtnouJiWnwtYcPH67LvP32202qiyO1e/2FmwcMGKBf88orrzSeO3fugl/r22+/1a+jehKawlHb3JL33nvPYi8Z57p1210t6WI6n44dO9Zm53p7Od9VD69awF3tN3v27AteJoBru23avTau7W3f5pZwbW+bdufa3nyffPKJ/hzUMjXt8dp+PgSqreCRRx7RH5IaBrh9+/YGy5WXlxu9vLx02R9++MFimUsuuURvV+tJWbJ169aaG5nHH3+82XW1xs37Cy+8oF/j0ksvtbj9+++/19u9vb2NFRUVNc9v2bJFP+/h4WExsCotLa0ZdpWQkHDeejhau9debNu0SLday1G1W0uoYR6mIY3n46htfr513y6++OI6z3OuW7fdTefd+PHj2+xcby/n+9GjR2uGbN1xxx0tuoHk2m6bdjfh2t72bd4Qru1t0+5c25vv66+/1p/FoEGD2t21vSkIVK3sT3/6U5NuZJq6KLy6uWtoUfjExESjn5/fBd+4W+vmXX3bYnqN1NRUmywc7IjtruTl5emLk7WCVEXNbVWvN2nSpEbLOWqbN0Sdo8OGDdPHuPvuu822ca5bp90rKyuNwcHBup2XLVvWJud6eznff/31Vz0v1lo3kFzbbdPuCtf2tm/zhnBtb5t259p+YR566CH9eahe0vZ0bW8qAlUrUkOETEPCmnIjo+zatcvo5OSkT5b169fXPF9SUqIDD/V606ZNM9tPDTkzJW650Bv35t689+vXTz/UTVR9N954Y82w09rBkvqmR722s7Ozce/evWb7qaQzaj914VMJC0zU76aL4VtvvdVovRy13dVk+iFDhlhs98Z8/vnnxp07d5o9r4YoqqQypuEeGzZsaPA1HLXN1YX58OHDFofnqQu6en03NzfjwYMHzcpwrrfsGlP7/DUFjOc7561xrreX811dM8PDw/V+s2bNatZNAtd2+2p3ru1t3+Zc2213jTHh2t7wsPPDFu47VE+n2qbuOdRn8s0337Sb+/bmcFL/sc5sV8f25Zdf6oQXpoVy1YK3lgQFBdWk8TZ54403dKIGlfhGLUKv1gNUix1nZWVJv379dDINtV/9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", "text/plain": [ "
" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "\n", "
\n", "
\n", " \n", " GoldenViz report\n", " Automatic visual QA for the 25 Golden Rules.\n", " \n", "
\n", "
\n", " PASS 25\n", " WARNING 0\n", " FAIL 0\n", "
\n", "
\n", " View warnings and failures\n", " \n", "
\n", "
Axis: Revenue trend by year
\n", "
Needs attention (0)
\n", "
No warnings or failures for this axis.
\n", "
\n", " Passing checks (25)\n", "
\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
RuleStatusAssessment
Clear title\n", " PASS\n", " \n", "
Title detected: 'Revenue trend by year'.
\n", " \n", "
Axis labels\n", " PASS\n", " \n", "
Both x-axis and y-axis labels are present.
\n", " \n", "
Units and scale clarity\n", " PASS\n", " \n", "
Numeric labels include detectable units or scale where applicable.
\n", " \n", "
Legend clarity\n", " PASS\n", " \n", "
No obvious legend clarity issue detected.
\n", " \n", "
Annotation context\n", " PASS\n", " \n", "
No obvious annotation context issue detected.
\n", "
Revenue trend by year
\n", "
Uncertainty cues\n", " PASS\n", " \n", "
No uncertainty cue issue detected.
\n", "
Revenue trend by year
\n", "
Readable labels and ticks\n", " PASS\n", " \n", "
No obvious readability issue detected.
\n", " \n", "
Color accessibility\n", " PASS\n", " \n", "
No obvious color accessibility issue detected.
\n", " \n", "
Direct labeling\n", " PASS\n", " \n", "
No direct-labeling opportunity detected.
\n", " \n", "
Avoid chartjunk\n", " PASS\n", " \n", "
No obvious chartjunk issue detected.
\n", "
Revenue trend by year
\n", "
Too many categories\n", " PASS\n", " \n", "
Category count appears manageable.
\n", "
Revenue trend by year
\n", "
Sort categorical bars\n", " PASS\n", " \n", "
No categorical bar sorting issue detected.
\n", "
Revenue trend by year
\n", "
Scatter overplotting\n", " PASS\n", " \n", "
No scatter overplotting issue detected.
\n", "
Revenue trend by year
\n", "
Decimal precision\n", " PASS\n", " \n", "
Tick precision appears readable.
\n", "
Revenue trend by year
\n", "
Date axis formatting\n", " PASS\n", " \n", "
No obvious date-axis formatting issue detected.
\n", "
Revenue trend by year
\n", "
Visual economy\n", " PASS\n", " \n", "
Chart appears visually economical.
\n", "
Revenue trend by year
\n", "
Appropriate scale\n", " PASS\n", " \n", "
No obvious scale issue detected.
\n", " \n", "
Chart type\n", " PASS\n", " \n", "
Detected chart type: line.
\n", " \n", "
Color map quality\n", " PASS\n", " \n", "
No problematic color map detected.
\n", " \n", "
Avoid dual axes\n", " PASS\n", " \n", "
No dual-axis layout detected.
\n", "
Revenue trend by year
\n", "
Area baseline\n", " PASS\n", " \n", "
No area baseline issue detected.
\n", "
Revenue trend by year
\n", "
Aspect ratio sanity\n", " PASS\n", " \n", "
Figure aspect ratio appears reasonable.
\n", "
Revenue trend by year
\n", "
Histogram bin quality\n", " PASS\n", " \n", "
No histogram bin issue detected.
\n", "
Revenue trend by year
\n", "
Category color consistency\n", " PASS\n", " \n", "
No category color issue detected.
\n", "
Revenue trend by year
\n", "
Diverging zero reference\n", " PASS\n", " \n", "
No diverging zero-reference issue detected.
\n", "
Revenue trend by year
\n", "
\n", " \n", "
\n", "
\n", "
\n", " \n", "
\n", "
\n", " " ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "import matplotlib.pyplot as plt\n", "from IPython.display import HTML, display\n", "from pathlib import Path\n", "import GoldenViz as gv\n", "\n", "fig, ax = plt.subplots(figsize=(6, 3.2))\n", "ax.plot([2021, 2022, 2023], [10, 13, 16])\n", "ax.set_title(\"Revenue trend by year\")\n", "ax.set_xlabel(\"Year\")\n", "ax.set_ylabel(\"Revenue (M EUR)\")\n", "\n", "# The chart output appears first.\n", "display(fig)\n", "\n", "# GoldenViz analyzes the figure; the HTML report below is embedded in this notebook.\n", "report = gv.analyze(fig)\n", "report_html = Path(\"_static/goldenviz_installation_check_report.html\")\n", "if not report_html.exists():\n", " report_html = Path(\"docs/_static/goldenviz_installation_check_report.html\")\n", "display(HTML(report_html.read_text(encoding=\"utf-8\")))\n", "plt.close(fig)\n" ] }, { "cell_type": "markdown", "id": "29dfe885", "metadata": {}, "source": [ "## Completeness rules\n", "\n", "Rules 1-6 check whether the chart contains enough information to be understood on its own." ] }, { "cell_type": "markdown", "id": "c696b0ed", "metadata": {}, "source": [ "### Rule 1 · Clear title\n", "\n", "A title should tell the reader what the chart is about before they inspect the marks." ] }, { "cell_type": "markdown", "id": "b93b295a", "metadata": {}, "source": [ "
\n", "
\n", "
\n", " Bad chart code\n", "
import matplotlib.pyplot as plt\n",
    " \n",
    "months = ["Jan", "Feb", "Mar", "Apr", "May", "Jun"]\n",
    "revenue = [18, 20, 21, 23, 25, 28]\n",
    " \n",
    "fig, ax = plt.subplots(figsize=(6.4, 3.8))\n",
    "ax.plot(months, revenue, marker="o")\n",
    "ax.set_xlabel("Month")\n",
    "ax.set_ylabel("Revenue (k EUR)")\n",
    "plt.show()
\n", "
\n", "
\n", "
\n", " \"Rule\n", "
\n", "
" ] }, { "cell_type": "markdown", "id": "e9af5881", "metadata": {}, "source": [ "
\n", "
\n", "
\n", " Good chart code\n", "
import matplotlib.pyplot as plt\n",
    " \n",
    "months = ["Jan", "Feb", "Mar", "Apr", "May", "Jun"]\n",
    "revenue = [18, 20, 21, 23, 25, 28]\n",
    " \n",
    "fig, ax = plt.subplots(figsize=(6.4, 3.8))\n",
    "ax.plot(months, revenue, marker="o")\n",
    "ax.set_title("Monthly revenue increased from Jan to Jun 2026")\n",
    "ax.set_xlabel("Month")\n",
    "ax.set_ylabel("Revenue (k EUR)")\n",
    "plt.show()
\n", "
\n", "
\n", "
\n", " \"Rule\n", "
\n", "
" ] }, { "cell_type": "markdown", "id": "f6d03c4b", "metadata": {}, "source": [ "### Rule 2 · Axis labels\n", "\n", "Axis labels and units make the measurement unambiguous." ] }, { "cell_type": "markdown", "id": "808c84b9", "metadata": {}, "source": [ "
\n", "
\n", "
\n", " Bad chart code\n", "
import matplotlib.pyplot as plt\n",
    " \n",
    "ad_spend = [8, 12, 16, 20, 24, 30, 34, 38]\n",
    "signups = [110, 140, 175, 205, 245, 310, 335, 390]\n",
    " \n",
    "fig, ax = plt.subplots(figsize=(6.4, 3.8))\n",
    "ax.scatter(ad_spend, signups)\n",
    "ax.set_title("Campaign performance")\n",
    "plt.show()
\n", "
\n", "
\n", "
\n", " \"Rule\n", "
\n", "
" ] }, { "cell_type": "markdown", "id": "16c599ae", "metadata": {}, "source": [ "
\n", "
\n", "
\n", " Good chart code\n", "
import matplotlib.pyplot as plt\n",
    " \n",
    "ad_spend = [8, 12, 16, 20, 24, 30, 34, 38]\n",
    "signups = [110, 140, 175, 205, 245, 310, 335, 390]\n",
    " \n",
    "fig, ax = plt.subplots(figsize=(6.4, 3.8))\n",
    "ax.scatter(ad_spend, signups)\n",
    "ax.set_title("Campaign performance")\n",
    "ax.set_xlabel("Ad spend (k EUR)")\n",
    "ax.set_ylabel("New signups")\n",
    "plt.show()
\n", "
\n", "
\n", "
\n", " \"Rule\n", "
\n", "
" ] }, { "cell_type": "markdown", "id": "623eae39", "metadata": {}, "source": [ "### Rule 3 · Units and scale clarity\n", "\n", "Large values should be scaled and labeled so the reader knows what the numbers mean." ] }, { "cell_type": "markdown", "id": "73020e60", "metadata": {}, "source": [ "
\n", "
\n", "
\n", " Bad chart code\n", "
import matplotlib.pyplot as plt\n",
    " \n",
    "years = [2022, 2023, 2024, 2025]\n",
    "revenue = [1250000, 1480000, 1730000, 1910000]\n",
    " \n",
    "fig, ax = plt.subplots(figsize=(6.4, 3.8))\n",
    "ax.plot(years, revenue, marker="o")\n",
    "ax.set_title("Revenue trend")\n",
    "ax.set_ylabel("Revenue")\n",
    "plt.show()
\n", "
\n", "
\n", "
\n", " \"Rule\n", "
\n", "
" ] }, { "cell_type": "markdown", "id": "3cbdf810", "metadata": {}, "source": [ "
\n", "
\n", "
\n", " Good chart code\n", "
import matplotlib.pyplot as plt\n",
    " \n",
    "years = [2022, 2023, 2024, 2025]\n",
    "revenue = [1250000, 1480000, 1730000, 1910000]\n",
    "revenue_millions = [value / 1_000_000 for value in revenue]\n",
    " \n",
    "fig, ax = plt.subplots(figsize=(6.4, 3.8))\n",
    "ax.plot(years, revenue_millions, marker="o")\n",
    "ax.set_title("Revenue trend")\n",
    "ax.set_xlabel("Year")\n",
    "ax.set_ylabel("Revenue (million EUR)")\n",
    "plt.show()
\n", "
\n", "
\n", "
\n", " \"Rule\n", "
\n", "
" ] }, { "cell_type": "markdown", "id": "dc812695", "metadata": {}, "source": [ "### Rule 4 · Legend clarity\n", "\n", "Multiple series need clear labels so readers can identify each line." ] }, { "cell_type": "markdown", "id": "566c5dc6", "metadata": {}, "source": [ "
\n", "
\n", "
\n", " Bad chart code\n", "
import matplotlib.pyplot as plt\n",
    " \n",
    "years = [2021, 2022, 2023, 2024, 2025]\n",
    "series = {\n",
    "    "Basic": [12, 14, 16, 18, 20],\n",
    "    "Pro": [9, 13, 17, 22, 28],\n",
    "    "Enterprise": [6, 8, 12, 17, 25],\n",
    "}\n",
    " \n",
    "fig, ax = plt.subplots(figsize=(6.4, 3.8))\n",
    "for values in series.values():\n",
    "    ax.plot(years, values, marker="o")\n",
    "ax.set_title("Subscriptions by plan")\n",
    "ax.set_ylabel("Subscriptions (k)")\n",
    "plt.show()
\n", "
\n", "
\n", "
\n", " \"Rule\n", "
\n", "
" ] }, { "cell_type": "markdown", "id": "314e9f1e", "metadata": {}, "source": [ "
\n", "
\n", "
\n", " Good chart code\n", "
import matplotlib.pyplot as plt\n",
    " \n",
    "years = [2021, 2022, 2023, 2024, 2025]\n",
    "series = {\n",
    "    "Basic": [12, 14, 16, 18, 20],\n",
    "    "Pro": [9, 13, 17, 22, 28],\n",
    "    "Enterprise": [6, 8, 12, 17, 25],\n",
    "}\n",
    " \n",
    "fig, ax = plt.subplots(figsize=(6.4, 3.8))\n",
    "for label, values in series.items():\n",
    "    ax.plot(years, values, marker="o", label=label)\n",
    "ax.legend(loc="center left", bbox_to_anchor=(1.02, 0.5))\n",
    "ax.set_title("Subscriptions by plan")\n",
    "ax.set_ylabel("Subscriptions (k)")\n",
    "plt.show()
\n", "
\n", "
\n", "
\n", " \"Rule\n", "
\n", "
" ] }, { "cell_type": "markdown", "id": "74aa4054", "metadata": {}, "source": [ "### Rule 5 · Annotation context\n", "\n", "Important events or takeaways should be visible when they explain the pattern." ] }, { "cell_type": "markdown", "id": "280b4e3f", "metadata": {}, "source": [ "
\n", "
\n", "
\n", " Bad chart code\n", "
import matplotlib.pyplot as plt\n",
    " \n",
    "weeks = [1, 2, 3, 4, 5, 6, 7, 8]\n",
    "adoption = [12, 15, 18, 23, 34, 39, 43, 46]\n",
    " \n",
    "fig, ax = plt.subplots(figsize=(6.4, 3.8))\n",
    "ax.plot(weeks, adoption, marker="o")\n",
    "ax.set_title("Feature adoption")\n",
    "ax.set_xlabel("Week")\n",
    "ax.set_ylabel("Adoption (%)")\n",
    "plt.show()
\n", "
\n", "
\n", "
\n", " \"Rule\n", "
\n", "
" ] }, { "cell_type": "markdown", "id": "dd06b9ce", "metadata": {}, "source": [ "
\n", "
\n", "
\n", " Good chart code\n", "
import matplotlib.pyplot as plt\n",
    " \n",
    "weeks = [1, 2, 3, 4, 5, 6, 7, 8]\n",
    "adoption = [12, 15, 18, 23, 34, 39, 43, 46]\n",
    " \n",
    "fig, ax = plt.subplots(figsize=(6.4, 3.8))\n",
    "ax.plot(weeks, adoption, marker="o")\n",
    "ax.annotate("Onboarding email launched", xy=(5, 34), xytext=(3.2, 42), arrowprops={"arrowstyle": "->"})\n",
    "ax.set_title("Feature adoption increased after onboarding email")\n",
    "ax.set_xlabel("Week")\n",
    "ax.set_ylabel("Adoption (%)")\n",
    "plt.show()
\n", "
\n", "
\n", "
\n", " \"Rule\n", "
\n", "
" ] }, { "cell_type": "markdown", "id": "0d931951", "metadata": {}, "source": [ "### Rule 6 · Uncertainty cues\n", "\n", "Estimates should show uncertainty when the uncertainty matters." ] }, { "cell_type": "markdown", "id": "bbfa96f8", "metadata": {}, "source": [ "
\n", "
\n", "
\n", " Bad chart code\n", "
import matplotlib.pyplot as plt\n",
    " \n",
    "groups = ["A", "B", "C", "D"]\n",
    "mean = [52, 57, 61, 55]\n",
    "error = [4, 7, 3, 6]\n",
    " \n",
    "fig, ax = plt.subplots(figsize=(6.4, 3.8))\n",
    "ax.bar(groups, mean)\n",
    "ax.set_title("Average test result")\n",
    "ax.set_ylabel("Score")\n",
    "plt.show()
\n", "
\n", "
\n", "
\n", " \"Rule\n", "
\n", "
" ] }, { "cell_type": "markdown", "id": "61483f10", "metadata": {}, "source": [ "
\n", "
\n", "
\n", " Good chart code\n", "
import matplotlib.pyplot as plt\n",
    " \n",
    "groups = ["A", "B", "C", "D"]\n",
    "mean = [52, 57, 61, 55]\n",
    "error = [4, 7, 3, 6]\n",
    " \n",
    "fig, ax = plt.subplots(figsize=(6.4, 3.8))\n",
    "ax.bar(groups, mean, yerr=error, capsize=6)\n",
    "ax.set_title("Average test result with uncertainty")\n",
    "ax.set_ylabel("Score")\n",
    "plt.show()
\n", "
\n", "
\n", "
\n", " \"Rule\n", "
\n", "
" ] }, { "cell_type": "markdown", "id": "8d378c56", "metadata": {}, "source": [ "## Readability rules\n", "\n", "Rules 7-16 check whether the chart can be read, scanned, and compared without unnecessary effort." ] }, { "cell_type": "markdown", "id": "65369acf", "metadata": {}, "source": [ "### Rule 7 · Readable labels\n", "\n", "Long labels should not collide or force the reader to decode a crowded axis." ] }, { "cell_type": "markdown", "id": "9fe3d273", "metadata": {}, "source": [ "
\n", "
\n", "
\n", " Bad chart code\n", "
import matplotlib.pyplot as plt\n",
    " \n",
    "segments = [\n",
    "    "Returning enterprise customers",\n",
    "    "New small business customers",\n",
    "    "One-time promotional buyers",\n",
    "    "Students using education plan",\n",
    "    "Trial users awaiting onboarding",\n",
    "]\n",
    "counts = [180, 145, 96, 125, 72]\n",
    " \n",
    "fig, ax = plt.subplots(figsize=(6.4, 3.8))\n",
    "ax.bar(segments, counts)\n",
    "ax.set_title("Customers by segment")\n",
    "plt.show()
\n", "
\n", "
\n", "
\n", " \"Rule\n", "
\n", "
" ] }, { "cell_type": "markdown", "id": "f32ffa19", "metadata": {}, "source": [ "
\n", "
\n", "
\n", " Good chart code\n", "
import matplotlib.pyplot as plt\n",
    "import textwrap\n",
    " \n",
    "segments = [\n",
    "    "Returning enterprise customers",\n",
    "    "New small business customers",\n",
    "    "One-time promotional buyers",\n",
    "    "Students using education plan",\n",
    "    "Trial users awaiting onboarding",\n",
    "]\n",
    "counts = [180, 145, 96, 125, 72]\n",
    "labels = [textwrap.fill(s, 22) for s in segments]\n",
    "pairs = sorted(zip(counts, labels))\n",
    " \n",
    "fig, ax = plt.subplots(figsize=(6.4, 3.8))\n",
    "ax.barh([label for _, label in pairs], [count for count, _ in pairs])\n",
    "ax.set_title("Customers by segment")\n",
    "ax.set_xlabel("Customers")\n",
    "plt.show()
\n", "
\n", "
\n", "
\n", " \"Rule\n", "
\n", "
" ] }, { "cell_type": "markdown", "id": "55cee0f6", "metadata": {}, "source": [ "### Rule 8 · Color accessibility\n", "\n", "Charts should remain readable for people with color-vision deficiencies." ] }, { "cell_type": "markdown", "id": "4cbd5455", "metadata": {}, "source": [ "
\n", "
\n", "
\n", " Bad chart code\n", "
import matplotlib.pyplot as plt\n",
    " \n",
    "segments = ["Home", "Food", "Auto", "Health", "Shopping"]\n",
    "spend = [42, 26, 18, 12, 8]\n",
    "colors = ["#d7191c", "#fdae61", "#ffffbf", "#a6d96a", "#1a9641"]\n",
    " \n",
    "fig, ax = plt.subplots(figsize=(6.4, 3.8))\n",
    "ax.bar(segments, spend, color=colors)\n",
    "ax.set_title("Household spend by category")\n",
    "ax.set_ylabel("Spend (%)")\n",
    "plt.show()
\n", "
\n", "
\n", "
\n", " \"Rule\n", "
\n", "
" ] }, { "cell_type": "markdown", "id": "be66cb18", "metadata": {}, "source": [ "
\n", "
\n", "
\n", " Good chart code\n", "
import matplotlib.pyplot as plt\n",
    " \n",
    "segments = ["Home", "Food", "Auto", "Health", "Shopping"]\n",
    "spend = [42, 26, 18, 12, 8]\n",
    "colors = ["#0072B2", "#E69F00", "#56B4E9", "#009E73", "#CC79A7"]\n",
    "hatches = ["", "//", "\\\\", "..", "xx"]\n",
    " \n",
    "fig, ax = plt.subplots(figsize=(6.4, 3.8))\n",
    "bars = ax.bar(segments, spend, color=colors)\n",
    "for bar, hatch in zip(bars, hatches):\n",
    "    bar.set_hatch(hatch)\n",
    "ax.set_title("Household spend by category")\n",
    "ax.set_ylabel("Spend (%)")\n",
    "plt.show()
\n", "
\n", "
\n", "
\n", " \"Rule\n", "
\n", "
" ] }, { "cell_type": "markdown", "id": "215fc162", "metadata": {}, "source": [ "### Rule 9 · Direct labeling\n", "\n", "When lines are easy to label directly, readers should not have to bounce between the plot and legend." ] }, { "cell_type": "markdown", "id": "6e71abb8", "metadata": {}, "source": [ "
\n", "
\n", "
\n", " Bad chart code\n", "
import matplotlib.pyplot as plt\n",
    " \n",
    "years = [2021, 2022, 2023, 2024, 2025]\n",
    "series = {\n",
    "    "Basic": [12, 14, 16, 18, 20],\n",
    "    "Pro": [9, 13, 17, 22, 28],\n",
    "    "Enterprise": [6, 8, 12, 17, 25],\n",
    "    "Education": [4, 7, 10, 13, 19],\n",
    "}\n",
    " \n",
    "fig, ax = plt.subplots(figsize=(6.4, 3.8))\n",
    "for label, values in series.items():\n",
    "    ax.plot(years, values, marker="o", label=label)\n",
    "ax.legend()\n",
    "ax.set_title("Subscriptions by plan")\n",
    "ax.set_ylabel("Subscriptions (k)")\n",
    "plt.show()
\n", "
\n", "
\n", "
\n", " \"Rule\n", "
\n", "
" ] }, { "cell_type": "markdown", "id": "48f5cc9e", "metadata": {}, "source": [ "
\n", "
\n", "
\n", " Good chart code\n", "
import matplotlib.pyplot as plt\n",
    " \n",
    "years = [2021, 2022, 2023, 2024, 2025]\n",
    "series = {\n",
    "    "Basic": [12, 14, 16, 18, 20],\n",
    "    "Pro": [9, 13, 17, 22, 28],\n",
    "    "Enterprise": [6, 8, 12, 17, 25],\n",
    "    "Education": [4, 7, 10, 13, 19],\n",
    "}\n",
    " \n",
    "fig, ax = plt.subplots(figsize=(6.4, 3.8))\n",
    "for label, values in series.items():\n",
    "    ax.plot(years, values, marker="o")\n",
    "    ax.text(years[-1] + 0.05, values[-1], label, va="center")\n",
    "ax.set_xlim(2021, 2025.9)\n",
    "ax.set_title("Subscriptions by plan")\n",
    "ax.set_ylabel("Subscriptions (k)")\n",
    "plt.show()
\n", "
\n", "
\n", "
\n", " \"Rule\n", "
\n", "
" ] }, { "cell_type": "markdown", "id": "2909f1dc", "metadata": {}, "source": [ "### Rule 10 · Avoid chartjunk\n", "\n", "Decoration should not compete with the data." ] }, { "cell_type": "markdown", "id": "c5ac6aa2", "metadata": {}, "source": [ "
\n", "
\n", "
\n", " Bad chart code\n", "
import matplotlib.pyplot as plt\n",
    " \n",
    "regions = ["North", "South", "East", "West"]\n",
    "profit = [18, 12, 15, 21]\n",
    " \n",
    "fig, ax = plt.subplots(figsize=(6.4, 3.8))\n",
    "ax.set_facecolor("#f3d9a5")\n",
    "ax.bar(regions, profit, edgecolor="black", linewidth=2)\n",
    "ax.grid(True, axis="both")\n",
    "ax.set_title("!!! PROFIT !!!")\n",
    "ax.set_ylabel("Profit (k EUR)")\n",
    "plt.show()
\n", "
\n", "
\n", "
\n", " \"Rule\n", "
\n", "
" ] }, { "cell_type": "markdown", "id": "21781b2c", "metadata": {}, "source": [ "
\n", "
\n", "
\n", " Good chart code\n", "
import matplotlib.pyplot as plt\n",
    " \n",
    "regions = ["North", "South", "East", "West"]\n",
    "profit = [18, 12, 15, 21]\n",
    " \n",
    "fig, ax = plt.subplots(figsize=(6.4, 3.8))\n",
    "ax.bar(regions, profit)\n",
    "ax.grid(True, axis="y")\n",
    "ax.set_title("Profit by region")\n",
    "ax.set_ylabel("Profit (k EUR)")\n",
    "plt.show()
\n", "
\n", "
\n", "
\n", " \"Rule\n", "
\n", "
" ] }, { "cell_type": "markdown", "id": "1613b022", "metadata": {}, "source": [ "### Rule 11 · Too many categories\n", "\n", "Too many categories make comparison slow and crowded." ] }, { "cell_type": "markdown", "id": "cf8464c3", "metadata": {}, "source": [ "
\n", "
\n", "
\n", " Bad chart code\n", "
import matplotlib.pyplot as plt\n",
    " \n",
    "categories = [f"C{i}" for i in range(1, 19)]\n",
    "values = [34, 28, 26, 22, 20, 18, 16, 12, 11, 10, 9, 8, 7, 6, 5, 5, 4, 3]\n",
    " \n",
    "fig, ax = plt.subplots(figsize=(6.4, 3.8))\n",
    "ax.bar(categories, values)\n",
    "ax.set_title("Requests by category")\n",
    "ax.set_ylabel("Requests")\n",
    "plt.show()
\n", "
\n", "
\n", "
\n", " \"Rule\n", "
\n", "
" ] }, { "cell_type": "markdown", "id": "33c00507", "metadata": {}, "source": [ "
\n", "
\n", "
\n", " Good chart code\n", "
import matplotlib.pyplot as plt\n",
    " \n",
    "categories = [f"C{i}" for i in range(1, 19)]\n",
    "values = [34, 28, 26, 22, 20, 18, 16, 12, 11, 10, 9, 8, 7, 6, 5, 5, 4, 3]\n",
    "top_labels = categories[:7] + ["Other"]\n",
    "top_values = values[:7] + [sum(values[7:])]\n",
    "pairs = sorted(zip(top_values, top_labels))\n",
    " \n",
    "fig, ax = plt.subplots(figsize=(6.4, 3.8))\n",
    "ax.barh([label for _, label in pairs], [value for value, _ in pairs])\n",
    "ax.set_title("Requests by category")\n",
    "ax.set_xlabel("Requests")\n",
    "plt.show()
\n", "
\n", "
\n", "
\n", " \"Rule\n", "
\n", "
" ] }, { "cell_type": "markdown", "id": "cf8ecf29", "metadata": {}, "source": [ "### Rule 12 · Sort categorical bars\n", "\n", "Sorted bars make ranking and comparison faster." ] }, { "cell_type": "markdown", "id": "640f2c9d", "metadata": {}, "source": [ "
\n", "
\n", "
\n", " Bad chart code\n", "
import matplotlib.pyplot as plt\n",
    " \n",
    "teams = ["Ops", "Sales", "Support", "Product", "Finance"]\n",
    "hours = [42, 18, 31, 24, 36]\n",
    " \n",
    "fig, ax = plt.subplots(figsize=(6.4, 3.8))\n",
    "ax.barh(teams, hours)\n",
    "ax.set_title("Average resolution time")\n",
    "ax.set_xlabel("Hours")\n",
    "plt.show()
\n", "
\n", "
\n", "
\n", " \"Rule\n", "
\n", "
" ] }, { "cell_type": "markdown", "id": "b7a8a6e5", "metadata": {}, "source": [ "
\n", "
\n", "
\n", " Good chart code\n", "
import matplotlib.pyplot as plt\n",
    " \n",
    "teams = ["Ops", "Sales", "Support", "Product", "Finance"]\n",
    "hours = [42, 18, 31, 24, 36]\n",
    "pairs = sorted(zip(hours, teams))\n",
    " \n",
    "fig, ax = plt.subplots(figsize=(6.4, 3.8))\n",
    "ax.barh([team for _, team in pairs], [hour for hour, _ in pairs])\n",
    "ax.set_title("Average resolution time")\n",
    "ax.set_xlabel("Hours")\n",
    "plt.show()
\n", "
\n", "
\n", "
\n", " \"Rule\n", "
\n", "
" ] }, { "cell_type": "markdown", "id": "c5cacebd", "metadata": {}, "source": [ "### Rule 13 · Scatter overplotting\n", "\n", "Repeated or dense points should reveal density instead of hiding it." ] }, { "cell_type": "markdown", "id": "fc3579d0", "metadata": {}, "source": [ "
\n", "
\n", "
\n", " Bad chart code\n", "
import matplotlib.pyplot as plt\n",
    "import numpy as np\n",
    " \n",
    "rng = np.random.default_rng(42)\n",
    "centers = np.array([[2, 2], [3, 3], [4, 2.5], [4.5, 4]])\n",
    "points = np.repeat(centers, [35, 45, 25, 30], axis=0)\n",
    "points = points + rng.normal(0, 0.04, size=(135, 2))\n",
    " \n",
    "fig, ax = plt.subplots(figsize=(6.4, 3.8))\n",
    "ax.scatter(points[:, 0], points[:, 1], s=28)\n",
    "ax.set_xlabel("Value score")\n",
    "ax.set_ylabel("Satisfaction score")\n",
    "plt.show()
\n", "
\n", "
\n", "
\n", " \"Rule\n", "
\n", "
" ] }, { "cell_type": "markdown", "id": "1856f46c", "metadata": {}, "source": [ "
\n", "
\n", "
\n", " Good chart code\n", "
import matplotlib.pyplot as plt\n",
    "import numpy as np\n",
    " \n",
    "centers = np.array([[2, 2], [3, 3], [4, 2.5], [4.5, 4]])\n",
    "counts = np.array([35, 45, 25, 30])\n",
    " \n",
    "fig, ax = plt.subplots(figsize=(6.4, 3.8))\n",
    "ax.scatter(centers[:, 0], centers[:, 1], s=counts * 18, alpha=0.55, edgecolor="black")\n",
    "ax.set_xlabel("Value score")\n",
    "ax.set_ylabel("Satisfaction score")\n",
    "ax.set_title("Point size shows repeated observations")\n",
    "plt.show()
\n", "
\n", "
\n", "
\n", " \"Rule\n", "
\n", "
" ] }, { "cell_type": "markdown", "id": "e0fb2b26", "metadata": {}, "source": [ "### Rule 14 · Decimal precision\n", "\n", "Labels should avoid unnecessary decimals that add noise without adding meaning." ] }, { "cell_type": "markdown", "id": "49815ffb", "metadata": {}, "source": [ "
\n", "
\n", "
\n", " Bad chart code\n", "
import matplotlib.pyplot as plt\n",
    " \n",
    "products = ["A", "B", "C", "D"]\n",
    "conversion = [12.3421, 11.9874, 13.2251, 12.7718]\n",
    " \n",
    "fig, ax = plt.subplots(figsize=(6.4, 3.8))\n",
    "bars = ax.bar(products, conversion)\n",
    "ax.bar_label(bars, fmt="%.4f%%")\n",
    "ax.set_ylim(0, 15)\n",
    "ax.set_ylabel("Conversion (%)")\n",
    "plt.show()
\n", "
\n", "
\n", "
\n", " \"Rule\n", "
\n", "
" ] }, { "cell_type": "markdown", "id": "da35303d", "metadata": {}, "source": [ "
\n", "
\n", "
\n", " Good chart code\n", "
import matplotlib.pyplot as plt\n",
    " \n",
    "products = ["A", "B", "C", "D"]\n",
    "conversion = [12.3421, 11.9874, 13.2251, 12.7718]\n",
    " \n",
    "fig, ax = plt.subplots(figsize=(6.4, 3.8))\n",
    "bars = ax.bar(products, conversion)\n",
    "ax.bar_label(bars, fmt="%.1f%%")\n",
    "ax.set_ylim(0, 15)\n",
    "ax.set_ylabel("Conversion (%)")\n",
    "plt.show()
\n", "
\n", "
\n", "
\n", " \"Rule\n", "
\n", "
" ] }, { "cell_type": "markdown", "id": "1f1d4f06", "metadata": {}, "source": [ "### Rule 15 · Date axis formatting\n", "\n", "Date ticks should be formatted at a readable interval." ] }, { "cell_type": "markdown", "id": "0a8cabcb", "metadata": {}, "source": [ "
\n", "
\n", "
\n", " Bad chart code\n", "
import matplotlib.pyplot as plt\n",
    "import numpy as np\n",
    " \n",
    "dates = [np.datetime64("2026-01-01") + np.timedelta64(i * 14, "D") for i in range(10)]\n",
    "visits = [120, 135, 128, 150, 162, 158, 170, 181, 190, 205]\n",
    " \n",
    "fig, ax = plt.subplots(figsize=(6.4, 3.8))\n",
    "ax.plot(dates, visits, marker="o")\n",
    "ax.set_title("Website visits")\n",
    "ax.set_ylabel("Visits (k)")\n",
    "plt.show()
\n", "
\n", "
\n", "
\n", " \"Rule\n", "
\n", "
" ] }, { "cell_type": "markdown", "id": "55103355", "metadata": {}, "source": [ "
\n", "
\n", "
\n", " Good chart code\n", "
import matplotlib.pyplot as plt\n",
    "import matplotlib.dates as mdates\n",
    "import numpy as np\n",
    " \n",
    "dates = [np.datetime64("2026-01-01") + np.timedelta64(i * 14, "D") for i in range(10)]\n",
    "visits = [120, 135, 128, 150, 162, 158, 170, 181, 190, 205]\n",
    " \n",
    "fig, ax = plt.subplots(figsize=(6.4, 3.8))\n",
    "ax.plot(dates, visits, marker="o")\n",
    "ax.set_title("Website visits")\n",
    "ax.set_ylabel("Visits (k)")\n",
    "ax.xaxis.set_major_locator(mdates.MonthLocator())\n",
    "ax.xaxis.set_major_formatter(mdates.DateFormatter("%b %Y"))\n",
    "ax.tick_params(axis="x", rotation=30)\n",
    "plt.show()
\n", "
\n", "
\n", "
\n", " \"Rule\n", "
\n", "
" ] }, { "cell_type": "markdown", "id": "bf7f1050", "metadata": {}, "source": [ "### Rule 16 · Visual economy\n", "\n", "Use enough visual encoding to explain the data, but avoid redundant styling." ] }, { "cell_type": "markdown", "id": "0ae1fd2d", "metadata": {}, "source": [ "
\n", "
\n", "
\n", " Bad chart code\n", "
import matplotlib.pyplot as plt\n",
    " \n",
    "products = ["A", "B", "C", "D", "E", "F"]\n",
    "values = [18, 25, 22, 31, 27, 20]\n",
    " \n",
    "fig, ax = plt.subplots(figsize=(6.4, 3.8))\n",
    "ax.bar(products, values, hatch="//", edgecolor="black")\n",
    "ax.plot(products, values, marker="D", color="red")\n",
    "ax.grid(True, axis="both")\n",
    "ax.set_title("Product sales with redundant styling")\n",
    "plt.show()
\n", "
\n", "
\n", "
\n", " \"Rule\n", "
\n", "
" ] }, { "cell_type": "markdown", "id": "92ede337", "metadata": {}, "source": [ "
\n", "
\n", "
\n", " Good chart code\n", "
import matplotlib.pyplot as plt\n",
    " \n",
    "products = ["A", "B", "C", "D", "E", "F"]\n",
    "values = [18, 25, 22, 31, 27, 20]\n",
    " \n",
    "fig, ax = plt.subplots(figsize=(6.4, 3.8))\n",
    "ax.bar(products, values)\n",
    "ax.grid(True, axis="y")\n",
    "ax.set_title("Product sales")\n",
    "ax.set_ylabel("Sales (k EUR)")\n",
    "plt.show()
\n", "
\n", "
\n", "
\n", " \"Rule\n", "
\n", "
" ] }, { "cell_type": "markdown", "id": "7cb55cf5", "metadata": {}, "source": [ "## Integrity rules\n", "\n", "Rules 17-25 check whether the chart avoids misleading scale, encoding, or comparison choices." ] }, { "cell_type": "markdown", "id": "aeb17191", "metadata": {}, "source": [ "### Rule 17 · Appropriate scale\n", "\n", "For bars, a truncated baseline can exaggerate small differences." ] }, { "cell_type": "markdown", "id": "08aa7e6a", "metadata": {}, "source": [ "
\n", "
\n", "
\n", " Bad chart code\n", "
import matplotlib.pyplot as plt\n",
    " \n",
    "branches = ["North", "Central", "South"]\n",
    "satisfaction = [82, 86, 88]\n",
    " \n",
    "fig, ax = plt.subplots(figsize=(6.4, 3.8))\n",
    "ax.bar(branches, satisfaction)\n",
    "ax.set_ylim(80, 90)\n",
    "ax.set_title("Customer satisfaction by branch")\n",
    "ax.set_ylabel("Satisfied customers (%)")\n",
    "plt.show()
\n", "
\n", "
\n", "
\n", " \"Rule\n", "
\n", "
" ] }, { "cell_type": "markdown", "id": "2da5e72e", "metadata": {}, "source": [ "
\n", "
\n", "
\n", " Good chart code\n", "
import matplotlib.pyplot as plt\n",
    " \n",
    "branches = ["North", "Central", "South"]\n",
    "satisfaction = [82, 86, 88]\n",
    " \n",
    "fig, ax = plt.subplots(figsize=(6.4, 3.8))\n",
    "ax.bar(branches, satisfaction)\n",
    "ax.set_ylim(0, 100)\n",
    "ax.set_title("Customer satisfaction by branch")\n",
    "ax.set_ylabel("Satisfied customers (%)")\n",
    "plt.show()
\n", "
\n", "
\n", "
\n", " \"Rule\n", "
\n", "
" ] }, { "cell_type": "markdown", "id": "14158f6e", "metadata": {}, "source": [ "### Rule 18 · Suitable chart type\n", "\n", "Categorical comparisons are easier to read as bars than as a line that implies sequence." ] }, { "cell_type": "markdown", "id": "6127ddb6", "metadata": {}, "source": [ "
\n", "
\n", "
\n", " Bad chart code\n", "
import matplotlib.pyplot as plt\n",
    " \n",
    "products = ["Shoes", "Bags", "Watches", "Perfume", "Jewelry"]\n",
    "sales = [54, 31, 46, 28, 62]\n",
    " \n",
    "fig, ax = plt.subplots(figsize=(6.4, 3.8))\n",
    "ax.plot(products, sales, marker="o")\n",
    "ax.set_title("Sales by product category")\n",
    "ax.set_ylabel("Sales (k EUR)")\n",
    "plt.show()
\n", "
\n", "
\n", "
\n", " \"Rule\n", "
\n", "
" ] }, { "cell_type": "markdown", "id": "2711c750", "metadata": {}, "source": [ "
\n", "
\n", "
\n", " Good chart code\n", "
import matplotlib.pyplot as plt\n",
    " \n",
    "products = ["Shoes", "Bags", "Watches", "Perfume", "Jewelry"]\n",
    "sales = [54, 31, 46, 28, 62]\n",
    "pairs = sorted(zip(sales, products))\n",
    " \n",
    "fig, ax = plt.subplots(figsize=(6.4, 3.8))\n",
    "ax.barh([p for _, p in pairs], [s for s, _ in pairs])\n",
    "ax.set_title("Sales by product category")\n",
    "ax.set_xlabel("Sales (k EUR)")\n",
    "plt.show()
\n", "
\n", "
\n", "
\n", " \"Rule\n", "
\n", "
" ] }, { "cell_type": "markdown", "id": "2b0df070", "metadata": {}, "source": [ "### Rule 19 · Color map quality\n", "\n", "Continuous color should use a perceptual scale and a labeled color bar." ] }, { "cell_type": "markdown", "id": "b61c3d23", "metadata": {}, "source": [ "
\n", "
\n", "
\n", " Bad chart code\n", "
import matplotlib.pyplot as plt\n",
    "import numpy as np\n",
    " \n",
    "heat = np.outer(np.linspace(0, 1, 12), np.linspace(0.2, 1, 12))\n",
    " \n",
    "fig, ax = plt.subplots(figsize=(6.4, 3.8))\n",
    "image = ax.imshow(heat, cmap="rainbow")\n",
    "ax.set_title("Demand intensity")\n",
    "fig.colorbar(image, ax=ax)\n",
    "plt.show()
\n", "
\n", "
\n", "
\n", " \"Rule\n", "
\n", "
" ] }, { "cell_type": "markdown", "id": "54479f28", "metadata": {}, "source": [ "
\n", "
\n", "
\n", " Good chart code\n", "
import matplotlib.pyplot as plt\n",
    "import numpy as np\n",
    " \n",
    "heat = np.outer(np.linspace(0, 1, 12), np.linspace(0.2, 1, 12))\n",
    " \n",
    "fig, ax = plt.subplots(figsize=(6.4, 3.8))\n",
    "image = ax.imshow(heat, cmap="viridis")\n",
    "ax.set_title("Demand intensity")\n",
    "colorbar = fig.colorbar(image, ax=ax)\n",
    "colorbar.set_label("Orders per store")\n",
    "plt.show()
\n", "
\n", "
\n", "
\n", " \"Rule\n", "
\n", "
" ] }, { "cell_type": "markdown", "id": "e39be5a0", "metadata": {}, "source": [ "### Rule 20 · Avoid dual axes\n", "\n", "Dual axes can imply relationships that come from scale choices rather than data." ] }, { "cell_type": "markdown", "id": "662a8c36", "metadata": {}, "source": [ "
\n", "
\n", "
\n", " Bad chart code\n", "
import matplotlib.pyplot as plt\n",
    " \n",
    "months = [1, 2, 3, 4, 5, 6]\n",
    "revenue = [1.2, 1.5, 1.8, 2.1, 2.4, 2.7]\n",
    "churn = [9, 8, 7, 6, 5, 4]\n",
    " \n",
    "fig, ax1 = plt.subplots(figsize=(6.4, 3.8))\n",
    "ax2 = ax1.twinx()\n",
    "ax1.plot(months, revenue, marker="o", label="Revenue")\n",
    "ax2.plot(months, churn, marker="o", color="red", label="Churn")\n",
    "ax1.set_ylabel("Revenue (M EUR)")\n",
    "ax2.set_ylabel("Churn (%)")\n",
    "plt.show()
\n", "
\n", "
\n", "
\n", " \"Rule\n", "
\n", "
" ] }, { "cell_type": "markdown", "id": "7aa4815a", "metadata": {}, "source": [ "
\n", "
\n", "
\n", " Good chart code\n", "
import matplotlib.pyplot as plt\n",
    " \n",
    "months = [1, 2, 3, 4, 5, 6]\n",
    "revenue = [1.2, 1.5, 1.8, 2.1, 2.4, 2.7]\n",
    "churn = [9, 8, 7, 6, 5, 4]\n",
    " \n",
    "fig, axes = plt.subplots(2, 1, figsize=(6.4, 4.2), sharex=True)\n",
    "axes[0].plot(months, revenue, marker="o")\n",
    "axes[0].set_ylabel("Revenue (M EUR)")\n",
    "axes[1].plot(months, churn, marker="o", color="red")\n",
    "axes[1].set_ylabel("Churn (%)")\n",
    "axes[1].set_xlabel("Month")\n",
    "plt.show()
\n", "
\n", "
\n", "
\n", " \"Rule\n", "
\n", "
" ] }, { "cell_type": "markdown", "id": "0a9abb09", "metadata": {}, "source": [ "### Rule 21 · Area baseline\n", "\n", "Filled areas should use an honest baseline because area size carries meaning." ] }, { "cell_type": "markdown", "id": "baec913a", "metadata": {}, "source": [ "
\n", "
\n", "
\n", " Bad chart code\n", "
import matplotlib.pyplot as plt\n",
    " \n",
    "years = [2020, 2021, 2022, 2023, 2024, 2025]\n",
    "share = [62, 64, 66, 67, 69, 70]\n",
    " \n",
    "fig, ax = plt.subplots(figsize=(6.4, 3.8))\n",
    "ax.fill_between(years, share, 60)\n",
    "ax.plot(years, share, marker="o")\n",
    "ax.set_ylim(60, 72)\n",
    "ax.set_ylabel("Share (%)")\n",
    "plt.show()
\n", "
\n", "
\n", "
\n", " \"Rule\n", "
\n", "
" ] }, { "cell_type": "markdown", "id": "07de0fd2", "metadata": {}, "source": [ "
\n", "
\n", "
\n", " Good chart code\n", "
import matplotlib.pyplot as plt\n",
    " \n",
    "years = [2020, 2021, 2022, 2023, 2024, 2025]\n",
    "share = [62, 64, 66, 67, 69, 70]\n",
    " \n",
    "fig, ax = plt.subplots(figsize=(6.4, 3.8))\n",
    "ax.fill_between(years, share, 0)\n",
    "ax.plot(years, share, marker="o")\n",
    "ax.set_ylim(0, 100)\n",
    "ax.set_ylabel("Share (%)")\n",
    "plt.show()
\n", "
\n", "
\n", "
\n", " \"Rule\n", "
\n", "
" ] }, { "cell_type": "markdown", "id": "e0e43e67", "metadata": {}, "source": [ "### Rule 22 · Aspect ratio sanity\n", "\n", "Extreme aspect ratios can flatten or exaggerate trends." ] }, { "cell_type": "markdown", "id": "aa2b34af", "metadata": {}, "source": [ "
\n", "
\n", "
\n", " Bad chart code\n", "
import matplotlib.pyplot as plt\n",
    " \n",
    "quarters = [1, 2, 3, 4, 5, 6, 7, 8]\n",
    "index = [12, 14, 15, 16, 18, 19, 21, 22]\n",
    " \n",
    "fig, ax = plt.subplots(figsize=(7.8, 2.2))\n",
    "ax.plot(quarters, index, marker="o")\n",
    "ax.set_title("Compressed aspect ratio hides the trend")\n",
    "plt.show()
\n", "
\n", "
\n", "
\n", " \"Rule\n", "
\n", "
" ] }, { "cell_type": "markdown", "id": "21a39443", "metadata": {}, "source": [ "
\n", "
\n", "
\n", " Good chart code\n", "
import matplotlib.pyplot as plt\n",
    " \n",
    "quarters = [1, 2, 3, 4, 5, 6, 7, 8]\n",
    "index = [12, 14, 15, 16, 18, 19, 21, 22]\n",
    " \n",
    "fig, ax = plt.subplots(figsize=(6.4, 3.8))\n",
    "ax.plot(quarters, index, marker="o")\n",
    "ax.set_title("Balanced aspect ratio shows the trend clearly")\n",
    "plt.show()
\n", "
\n", "
\n", "
\n", " \"Rule\n", "
\n", "
" ] }, { "cell_type": "markdown", "id": "4ab25f1c", "metadata": {}, "source": [ "### Rule 23 · Histogram bin quality\n", "\n", "A histogram needs enough bins to reveal the distribution shape without creating noise." ] }, { "cell_type": "markdown", "id": "3f08ca11", "metadata": {}, "source": [ "
\n", "
\n", "
\n", " Bad chart code\n", "
import matplotlib.pyplot as plt\n",
    "import numpy as np\n",
    " \n",
    "rng = np.random.default_rng(42)\n",
    "scores = rng.normal(72, 9, 420)\n",
    " \n",
    "fig, ax = plt.subplots(figsize=(6.4, 3.8))\n",
    "ax.hist(scores, bins=3)\n",
    "ax.set_title("Exam scores")\n",
    "ax.set_xlabel("Score")\n",
    "ax.set_ylabel("Students")\n",
    "plt.show()
\n", "
\n", "
\n", "
\n", " \"Rule\n", "
\n", "
" ] }, { "cell_type": "markdown", "id": "789ddc56", "metadata": {}, "source": [ "
\n", "
\n", "
\n", " Good chart code\n", "
import matplotlib.pyplot as plt\n",
    "import numpy as np\n",
    " \n",
    "rng = np.random.default_rng(42)\n",
    "scores = rng.normal(72, 9, 420)\n",
    " \n",
    "fig, ax = plt.subplots(figsize=(6.4, 3.8))\n",
    "ax.hist(scores, bins=18)\n",
    "ax.set_title("Exam scores")\n",
    "ax.set_xlabel("Score")\n",
    "ax.set_ylabel("Students")\n",
    "plt.show()
\n", "
\n", "
\n", "
\n", " \"Rule\n", "
\n", "
" ] }, { "cell_type": "markdown", "id": "a7503db9", "metadata": {}, "source": [ "### Rule 24 · Category color consistency\n", "\n", "The same category should keep the same color throughout a chart." ] }, { "cell_type": "markdown", "id": "61a8cd33", "metadata": {}, "source": [ "
\n", "
\n", "
\n", " Bad chart code\n", "
import matplotlib.pyplot as plt\n",
    " \n",
    "quarters = ["Q1", "Q2", "Q3"]\n",
    "desktop = [42, 45, 48]\n",
    "mobile = [31, 34, 38]\n",
    " \n",
    "fig, ax = plt.subplots(figsize=(6.4, 3.8))\n",
    "ax.plot(quarters, desktop, marker="o", color="blue", label="Desktop")\n",
    "ax.plot(quarters, mobile, marker="o", color="orange", label="Mobile")\n",
    "ax.scatter(["Q2"], [45], color="orange", s=90)\n",
    "ax.scatter(["Q2"], [34], color="blue", s=90)\n",
    "ax.legend()\n",
    "plt.show()
\n", "
\n", "
\n", "
\n", " \"Rule\n", "
\n", "
" ] }, { "cell_type": "markdown", "id": "2c028bb4", "metadata": {}, "source": [ "
\n", "
\n", "
\n", " Good chart code\n", "
import matplotlib.pyplot as plt\n",
    " \n",
    "quarters = ["Q1", "Q2", "Q3"]\n",
    "desktop = [42, 45, 48]\n",
    "mobile = [31, 34, 38]\n",
    " \n",
    "fig, ax = plt.subplots(figsize=(6.4, 3.8))\n",
    "ax.plot(quarters, desktop, marker="o", color="blue", label="Desktop")\n",
    "ax.plot(quarters, mobile, marker="o", color="orange", label="Mobile")\n",
    "ax.legend()\n",
    "ax.set_title("Traffic by device")\n",
    "ax.set_ylabel("Sessions (k)")\n",
    "plt.show()
\n", "
\n", "
\n", "
\n", " \"Rule\n", "
\n", "
" ] }, { "cell_type": "markdown", "id": "fbc5e2b4", "metadata": {}, "source": [ "### Rule 25 · Diverging zero reference\n", "\n", "Positive and negative values need a clear zero reference." ] }, { "cell_type": "markdown", "id": "5a569bb8", "metadata": {}, "source": [ "
\n", "
\n", "
\n", " Bad chart code\n", "
import matplotlib.pyplot as plt\n",
    " \n",
    "departments = ["Ops", "Sales", "Support", "Product"]\n",
    "delta = [-8, 12, -5, 9]\n",
    " \n",
    "fig, ax = plt.subplots(figsize=(6.4, 3.8))\n",
    "ax.bar(departments, delta)\n",
    "ax.set_title("Change vs target")\n",
    "ax.set_ylabel("Change (%)")\n",
    "plt.show()
\n", "
\n", "
\n", "
\n", " \"Rule\n", "
\n", "
" ] }, { "cell_type": "markdown", "id": "82ca9bb3", "metadata": {}, "source": [ "
\n", "
\n", "
\n", " Good chart code\n", "
import matplotlib.pyplot as plt\n",
    " \n",
    "departments = ["Ops", "Sales", "Support", "Product"]\n",
    "delta = [-8, 12, -5, 9]\n",
    "colors = ["#b42318" if value < 0 else "#2f855a" for value in delta]\n",
    " \n",
    "fig, ax = plt.subplots(figsize=(6.4, 3.8))\n",
    "ax.bar(departments, delta, color=colors)\n",
    "ax.axhline(0, color="black", linewidth=1.2)\n",
    "ax.set_title("Change vs target")\n",
    "ax.set_ylabel("Change (%)")\n",
    "plt.show()
\n", "
\n", "
\n", "
\n", " \"Rule\n", "
\n", "
" ] } ], "metadata": { "kernelspec": { "display_name": "Python 3", "language": "python", "name": "python3" }, "language_info": { "name": "python", "pygments_lexer": "ipython3" }, "nbsphinx": { "execute": "never" } }, "nbformat": 4, "nbformat_minor": 5 }