{"spec_id":"lollipop-basic","library":"plotnine","language":"python","code":"\"\"\" anyplot.ai\nlollipop-basic: Basic Lollipop Chart\nLibrary: plotnine 0.15.7 | Python 3.13.14\nQuality: 84/100 | Updated: 2026-07-01\n\"\"\"\n\nimport os\nimport sys\n\n\n# Prevent circular import: remove this script's directory from sys.path so\n# \"from plotnine import ...\" resolves to the installed library, not this file.\n_here = os.path.dirname(os.path.abspath(__file__))\nsys.path = [p for p in sys.path if os.path.abspath(p) != _here]\n\nimport pandas as pd\nfrom plotnine import (\n    aes,\n    element_blank,\n    element_line,\n    element_rect,\n    element_text,\n    geom_point,\n    geom_segment,\n    geom_text,\n    ggplot,\n    ggsave,\n    labs,\n    scale_size_continuous,\n    theme,\n    theme_minimal,\n)\n\n\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\"\nBRAND = \"#009E73\"\n\n# Product sales by category, sorted ascending for ranking narrative\ndata = {\n    \"category\": [\n        \"Electronics\",\n        \"Furniture\",\n        \"Clothing\",\n        \"Groceries\",\n        \"Sports\",\n        \"Books\",\n        \"Toys\",\n        \"Beauty\",\n        \"Garden\",\n        \"Automotive\",\n    ],\n    \"value\": [245, 198, 176, 152, 134, 118, 95, 87, 72, 58],\n}\n\ndf = pd.DataFrame(data)\ndf = df.sort_values(\"value\", ascending=True).reset_index(drop=True)\ndf[\"category\"] = pd.Categorical(df[\"category\"], categories=df[\"category\"], ordered=True)\ndf[\"label\"] = df[\"value\"].astype(str) + \"k\"\n\nplot = (\n    ggplot(df, aes(x=\"category\", y=\"value\"))\n    + geom_segment(aes(x=\"category\", xend=\"category\", y=0, yend=\"value\"), color=BRAND, size=0.6)\n    + geom_point(aes(size=\"value\"), color=BRAND, fill=BRAND, show_legend=False)\n    + geom_text(\n        aes(label=\"label\"),\n        color=INK_SOFT,\n        size=2.8,  # geom_text size is in mm (~2.8mm ≈ 8pt at dpi=400)\n        nudge_y=16,\n        va=\"bottom\",\n    )\n    + scale_size_continuous(range=[2, 7])\n    + labs(x=\"Product Category\", y=\"Sales (thousands $)\", title=\"lollipop-basic · python · plotnine · anyplot.ai\")\n    + theme_minimal()\n    + theme(\n        figure_size=(8, 4.5),\n        plot_background=element_rect(fill=PAGE_BG, color=PAGE_BG),\n        panel_background=element_rect(fill=PAGE_BG, color=PAGE_BG),\n        panel_border=element_blank(),\n        text=element_text(size=7, color=INK),\n        axis_title=element_text(size=10, color=INK),\n        axis_text=element_text(size=8, color=INK_SOFT),\n        axis_text_x=element_text(angle=45, ha=\"right\", color=INK_SOFT),\n        axis_line=element_line(color=INK_SOFT),\n        plot_title=element_text(size=12, color=INK),\n        panel_grid_minor=element_blank(),\n        panel_grid_major_x=element_blank(),\n        panel_grid_major_y=element_line(color=INK, alpha=0.15, size=0.3),\n    )\n)\n\nggsave(plot, filename=f\"plot-{THEME}.png\", dpi=400, width=8, height=4.5, units=\"in\")\n"}