{"spec_id":"wordcloud-basic","library":"plotnine","language":"python","code":"\"\"\" anyplot.ai\nwordcloud-basic: Basic Word Cloud\nLibrary: plotnine 0.15.7 | Python 3.13.14\nQuality: 85/100 | Updated: 2026-08-04\n\"\"\"\n\nimport os\n\nimport numpy as np\nimport pandas as pd\nfrom plotnine import (\n    aes,\n    annotate,\n    coord_cartesian,\n    element_blank,\n    element_rect,\n    element_text,\n    geom_text,\n    ggplot,\n    labs,\n    scale_alpha_identity,\n    scale_color_identity,\n    scale_size_identity,\n    theme,\n)\n\n\n# Theme tokens\nTHEME = os.getenv(\"ANYPLOT_THEME\", \"light\")\nPAGE_BG = \"#FAF8F1\" if THEME == \"light\" else \"#1A1A17\"\nINK = \"#1A1A17\" if THEME == \"light\" else \"#F0EFE8\"\nINK_SOFT = \"#4A4A44\" if THEME == \"light\" else \"#B8B7B0\"\n\n# Imprint palette for frequency tiers\nIMPRINT = [\"#009E73\", \"#C475FD\", \"#4467A3\", \"#BD8233\"]\n\n# Word frequency data - technology survey responses\nwords_data = {\n    \"word\": [\n        \"Python\",\n        \"Data\",\n        \"Machine\",\n        \"Learning\",\n        \"AI\",\n        \"Cloud\",\n        \"API\",\n        \"Database\",\n        \"Security\",\n        \"DevOps\",\n        \"Analytics\",\n        \"Automation\",\n        \"Software\",\n        \"Code\",\n        \"Development\",\n        \"Integration\",\n        \"Platform\",\n        \"Infrastructure\",\n        \"Testing\",\n        \"Deployment\",\n        \"Monitoring\",\n        \"Framework\",\n        \"Docker\",\n        \"AWS\",\n        \"Azure\",\n        \"Kubernetes\",\n        \"Terraform\",\n        \"GraphQL\",\n        \"Redis\",\n    ],\n    \"frequency\": [\n        95,\n        88,\n        82,\n        78,\n        75,\n        70,\n        65,\n        62,\n        58,\n        55,\n        52,\n        48,\n        45,\n        42,\n        38,\n        35,\n        32,\n        30,\n        28,\n        26,\n        24,\n        22,\n        20,\n        18,\n        16,\n        14,\n        11,\n        8,\n        6,\n    ],\n}\n\ndf = pd.DataFrame(words_data)\n\n# Calculate font sizes (6-25 mm) for emphasis, and a subtle alpha ramp for depth\nmin_freq, max_freq = df[\"frequency\"].min(), df[\"frequency\"].max()\nfreq_norm = (df[\"frequency\"] - min_freq) / (max_freq - min_freq)\ndf[\"size\"] = 6 + freq_norm * 19\ndf[\"alpha\"] = 0.6 + freq_norm * 0.4\n\n# Sort by frequency descending\ndf = df.sort_values(\"frequency\", ascending=False).reset_index(drop=True)\n\n# Hand-crafted positions to ensure no overlap\npositions = [\n    (45, 28),  # Python (largest) - center\n    (70, 36),  # Data\n    (22, 24),  # Machine\n    (72, 22),  # Learning\n    (30, 36),  # AI\n    (55, 16),  # Cloud\n    (18, 42),  # API\n    (45, 42),  # Database\n    (68, 46),  # Security\n    (25, 10),  # DevOps\n    (50, 6),  # Analytics\n    (78, 8),  # Automation\n    (6, 28),  # Software\n    (88, 28),  # Code\n    (35, 50),  # Development\n    (60, 50),  # Integration\n    (12, 50),  # Platform\n    (82, 50),  # Infrastructure\n    (6, 16),  # Testing\n    (6, 40),  # Deployment\n    (55, 36),  # Monitoring\n    (88, 40),  # Framework\n    (30, 6),  # Docker\n    (6, 6),  # AWS\n    (75, 6),  # Azure\n    (94, 10),  # Kubernetes - fills empty right margin below the legend\n    (94, 24),  # Terraform - fills empty right margin below the legend\n    (78, 53),  # GraphQL - fills empty upper-right quadrant\n    (42, 20),  # Redis - fills gap between the mid-canvas clusters\n]\n\ndf[\"x\"] = [p[0] for p in positions]\ndf[\"y\"] = [p[1] for p in positions]\n\n# AWS sits alone in the bottom-left corner - rotate it for an organic word-cloud feel\ndf[\"angle\"] = np.where(df[\"word\"] == \"AWS\", 90, 0)\n\n# Assign Imprint colors based on frequency tiers\ncolors = []\nfor freq in df[\"frequency\"]:\n    if freq >= 65:\n        colors.append(IMPRINT[0])  # Brand green - highest\n    elif freq >= 35:\n        colors.append(IMPRINT[1])  # Lavender - medium-high\n    elif freq >= 15:\n        colors.append(IMPRINT[2])  # Blue - medium-low\n    else:\n        colors.append(IMPRINT[3])  # Ochre - lowest\n\ndf[\"color\"] = colors\n\n# Create legend using colored text labels instead of bullets\nlegend_df = pd.DataFrame(\n    {\n        \"x\": [92, 92, 92, 92],\n        \"y\": [46, 42, 38, 34],\n        \"label\": [\"High (65+)\", \"Medium (35-64)\", \"Low-Med (15-34)\", \"Low (<15)\"],\n        \"color\": IMPRINT,\n    }\n)\n\n# Create plot\nplot = (\n    ggplot(df, aes(x=\"x\", y=\"y\", label=\"word\", size=\"size\", color=\"color\"))\n    + geom_text(aes(alpha=\"alpha\", angle=\"angle\"), family=\"sans-serif\", fontweight=\"normal\", show_legend=False)\n    + geom_text(\n        data=legend_df, mapping=aes(x=\"x\", y=\"y\", label=\"label\", color=\"color\"), size=4, ha=\"left\", show_legend=False\n    )\n    + annotate(\"text\", x=92, y=50, label=\"Frequency\", size=5.5, ha=\"left\", fontweight=\"bold\", color=INK)\n    + scale_size_identity()\n    + scale_color_identity()\n    + scale_alpha_identity()\n    + coord_cartesian(xlim=(0, 100), ylim=(0, 56.25), expand=False)\n    + labs(title=\"wordcloud-basic · plotnine · anyplot.ai\")\n    + theme(\n        figure_size=(8, 4.5),\n        plot_title=element_text(size=12, ha=\"center\", weight=\"bold\", color=INK, margin={\"b\": 8}),\n        panel_background=element_rect(fill=PAGE_BG, color=None),\n        plot_background=element_rect(fill=PAGE_BG, color=None),\n        panel_grid_major=element_blank(),\n        panel_grid_minor=element_blank(),\n        axis_text=element_blank(),\n        axis_title=element_blank(),\n        axis_ticks=element_blank(),\n    )\n)\n\n# Save\nplot.save(f\"plot-{THEME}.png\", dpi=400, width=8, height=4.5, units=\"in\", verbose=False)\n"}