{"spec_id":"pictogram-basic","library":"seaborn","language":"python","code":"\"\"\" anyplot.ai\npictogram-basic: Pictogram Chart (Isotype Visualization)\nLibrary: seaborn 0.13.2 | Python 3.13.13\nQuality: 87/100 | Updated: 2026-06-03\n\"\"\"\n\nimport os\nimport sys\n\n\n# Remove this file's directory from sys.path so \"import seaborn\" resolves to the library\n_this_dir = os.path.dirname(os.path.abspath(__file__))\nsys.path = [p for p in sys.path if p != _this_dir]\n\nimport matplotlib.pyplot as plt\nimport pandas as pd\nimport seaborn as sns\n\n\nTHEME = os.getenv(\"ANYPLOT_THEME\", \"light\")\n\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\"\nINK_MUTED = \"#6B6A63\" if THEME == \"light\" else \"#A8A79F\"\n\n# Imprint palette — canonical order, first series always #009E73\nIMPRINT_PALETTE = [\"#009E73\", \"#C475FD\", \"#4467A3\", \"#BD8233\", \"#AE3030\"]\n\n# Data — Developer survey: most-used programming languages (% of respondents)\ncategories = [\"Python\", \"JavaScript\", \"Java\", \"C++\", \"Go\"]\nvalues = [67, 55, 43, 32, 25]\nunit_value = 10  # each icon = 10% of respondents\n\n# Category colors from Imprint palette in canonical order\ncat_colors = {cat: IMPRINT_PALETTE[i] for i, cat in enumerate(categories)}\n\n# Build icon DataFrame — each row is one icon dot\nrows = []\nfor cat, val in zip(categories, values, strict=True):\n    full_icons = val // unit_value\n    partial = (val % unit_value) / unit_value\n    for j in range(full_icons):\n        rows.append({\"category\": cat, \"x\": j, \"icon_type\": \"full\"})\n    if partial > 0:\n        rows.append({\"category\": cat, \"x\": full_icons, \"icon_type\": \"partial\"})\n\ndf = pd.DataFrame(rows)\n\n# Theme-aware seaborn setup\nsns.set_theme(\n    style=\"white\",\n    rc={\n        \"figure.facecolor\": PAGE_BG,\n        \"axes.facecolor\": PAGE_BG,\n        \"axes.labelcolor\": INK_SOFT,\n        \"text.color\": INK,\n        \"xtick.color\": INK_SOFT,\n        \"ytick.color\": INK,\n        \"legend.facecolor\": ELEVATED_BG,\n        \"legend.edgecolor\": INK_SOFT,\n    },\n)\n\nfig, ax = plt.subplots(figsize=(8, 4.5), dpi=400)\nfig.set_facecolor(PAGE_BG)\nax.set_facecolor(PAGE_BG)\n\n# Full icons via seaborn stripplot — discrete dot placement along y-axis categories\ndf_full = df[df[\"icon_type\"] == \"full\"]\nif not df_full.empty:\n    sns.stripplot(\n        data=df_full,\n        x=\"x\",\n        y=\"category\",\n        hue=\"category\",\n        order=categories,\n        hue_order=categories,\n        palette=cat_colors,\n        size=14,\n        marker=\"o\",\n        edgecolor=PAGE_BG,\n        linewidth=0.8,\n        jitter=False,\n        dodge=False,\n        legend=False,\n        zorder=3,\n        ax=ax,\n    )\n\n# Partial icons — faded to signal fractional remainder\ndf_partial = df[df[\"icon_type\"] == \"partial\"]\nfor cat in categories:\n    cat_partial = df_partial[df_partial[\"category\"] == cat]\n    if not cat_partial.empty:\n        sns.stripplot(\n            data=cat_partial,\n            x=\"x\",\n            y=\"category\",\n            order=categories,\n            color=cat_colors[cat],\n            alpha=0.35,\n            size=14,\n            marker=\"o\",\n            edgecolor=cat_colors[cat],\n            linewidth=0.8,\n            jitter=False,\n            dodge=False,\n            legend=False,\n            zorder=3,\n            ax=ax,\n        )\n\n# Subtle highlight band for the top category row\nax.axhspan(-0.4, 0.4, color=IMPRINT_PALETTE[0], alpha=0.07, zorder=0)\n\n# Value annotations to the right of each row\nfor idx, (_cat, val) in enumerate(zip(categories, values, strict=True)):\n    total_icons = val // unit_value + (1 if val % unit_value > 0 else 0)\n    ax.text(\n        total_icons + 0.3,\n        idx,\n        f\"{val}%\",\n        fontsize=8,\n        va=\"center\",\n        ha=\"left\",\n        color=INK,\n        fontweight=\"bold\" if idx == 0 else \"normal\",\n    )\n\n# Axis styling\nax.set_xlabel(f\"Icons (each = {unit_value}% of respondents)\", fontsize=10, color=INK_SOFT, labelpad=8)\nax.set_ylabel(\"\")\nax.tick_params(axis=\"y\", length=0, pad=8, labelsize=8, colors=INK)\nax.tick_params(axis=\"x\", which=\"both\", bottom=False, labelbottom=False)\n\nmax_x_pos = max(v // unit_value + (1 if v % unit_value > 0 else 0) for v in values)\nax.set_xlim(-0.7, max_x_pos + 1.5)\n\nax.set_title(\"pictogram-basic · python · seaborn · anyplot.ai\", fontsize=12, fontweight=\"medium\", pad=14, color=INK)\n\nsns.despine(left=True, bottom=True, ax=ax)\n\n# Unit legend annotation — tertiary text\nax.annotate(\n    f\"● = {unit_value}% of respondents   (lighter = partial unit)\",\n    xy=(0.5, -0.10),\n    xycoords=\"axes fraction\",\n    fontsize=8,\n    ha=\"center\",\n    va=\"top\",\n    color=INK_MUTED,\n)\n\nplt.savefig(f\"plot-{THEME}.png\", dpi=400, facecolor=PAGE_BG)\nplt.close()\n"}