{"spec_id":"scatter-connected-temporal","library":"plotnine","language":"python","code":"\"\"\" anyplot.ai\nscatter-connected-temporal: Connected Scatter Plot with Temporal Path\nLibrary: plotnine 0.15.5 | Python 3.13.13\nQuality: 88/100 | Updated: 2026-06-09\n\"\"\"\n\nimport os\nimport sys\n\n\n# This file is named after the library it imports — remove its directory from\n# sys.path so Python finds the installed plotnine package, not this script.\n_here = os.path.dirname(os.path.abspath(__file__))\nif sys.path and os.path.abspath(sys.path[0]) == _here:\n    sys.path.pop(0)\n\nimport numpy as np\nimport pandas as pd\nfrom plotnine import (\n    aes,\n    annotate,\n    arrow,\n    element_blank,\n    element_line,\n    element_rect,\n    element_text,\n    geom_path,\n    geom_point,\n    geom_segment,\n    geom_text,\n    ggplot,\n    labs,\n    scale_color_gradient,\n    scale_fill_gradient,\n    scale_x_continuous,\n    scale_y_continuous,\n    theme,\n    theme_minimal,\n)\n\n\n# Theme-adaptive chrome tokens (Imprint palette — see prompts/default-style-guide.md)\nTHEME = os.getenv(\"ANYPLOT_THEME\", \"light\")\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\"\n\n# Imprint sequential gradient: brand green → blue (temporal progression low→high)\nSEQ_LOW = \"#009E73\"\nSEQ_HIGH = \"#4467A3\"\nRECESSION_COLOR = \"#AE3030\"  # Imprint matte red — semantic bad/crisis anchor\n\n# Data: US unemployment rate vs inflation rate (Phillips curve), 1990-2020\nnp.random.seed(42)\nyears = np.arange(1990, 2021)\nn = len(years)\n\nunemployment = np.array(\n    [\n        5.6,\n        6.8,\n        7.5,\n        6.9,\n        6.1,\n        5.6,\n        5.4,\n        4.9,\n        4.5,\n        4.2,\n        4.0,\n        4.7,\n        5.8,\n        6.0,\n        5.5,\n        5.1,\n        4.6,\n        4.6,\n        5.8,\n        9.3,\n        9.6,\n        8.9,\n        8.1,\n        7.4,\n        6.2,\n        5.3,\n        4.9,\n        4.4,\n        3.9,\n        3.7,\n        8.1,\n    ]\n)\ninflation = np.array(\n    [\n        5.4,\n        4.2,\n        3.0,\n        3.0,\n        2.6,\n        2.8,\n        3.0,\n        2.3,\n        1.6,\n        2.2,\n        3.4,\n        2.8,\n        1.6,\n        2.3,\n        2.7,\n        3.4,\n        3.2,\n        2.8,\n        3.8,\n        -0.4,\n        1.6,\n        3.2,\n        2.1,\n        1.5,\n        1.6,\n        0.1,\n        1.3,\n        2.1,\n        2.4,\n        1.8,\n        1.2,\n    ]\n)\n\ndf = pd.DataFrame(\n    {\"Unemployment\": unemployment, \"Inflation\": inflation, \"Year\": years, \"Year_num\": np.arange(n, dtype=float)}\n)\n\n# Four well-separated key years to anchor temporal reading (avoids central congestion)\nlabel_config = {1990: (-0.42, 0.55), 2000: (0.32, 0.55), 2010: (0.42, -0.60), 2020: (0.42, 0.55)}\n\nlabel_rows = []\nfor yr, (dx, dy) in label_config.items():\n    row = df[df[\"Year\"] == yr].iloc[0]\n    label_rows.append({\"x_label\": row[\"Unemployment\"] + dx, \"y_label\": row[\"Inflation\"] + dy, \"Label\": str(yr)})\ndf_labels = pd.DataFrame(label_rows)\n\nrecession_point = df[df[\"Year\"] == 2009].copy()\n\n# Directional arrow segments at inflection points to reinforce temporal flow\narrow_years = [1992, 1997, 2011, 2017]\narrow_rows = []\nfor yr in arrow_years:\n    r1 = df[df[\"Year\"] == yr].iloc[0]\n    r2 = df[df[\"Year\"] == yr + 1].iloc[0]\n    arrow_rows.append(\n        {\n            \"x\": r1[\"Unemployment\"],\n            \"y\": r1[\"Inflation\"],\n            \"xend\": r2[\"Unemployment\"],\n            \"yend\": r2[\"Inflation\"],\n            \"Year_num\": r1[\"Year_num\"],\n        }\n    )\ndf_arrows = pd.DataFrame(arrow_rows)\n\n# Plot — geom_path preserves temporal ordering (not geom_line which sorts by x)\nplot = (\n    ggplot(df, aes(x=\"Unemployment\", y=\"Inflation\"))\n    + geom_path(aes(color=\"Year_num\"), size=1.2)\n    + geom_segment(\n        data=df_arrows,\n        mapping=aes(x=\"x\", y=\"y\", xend=\"xend\", yend=\"yend\", color=\"Year_num\"),\n        arrow=arrow(length=0.1, type=\"open\"),\n        show_legend=False,\n        size=1.2,\n    )\n    + geom_point(aes(fill=\"Year_num\"), size=4.0, color=PAGE_BG, stroke=0.6, show_legend=False)\n    + geom_point(\n        data=recession_point,\n        mapping=aes(x=\"Unemployment\", y=\"Inflation\"),\n        size=7.5,\n        color=RECESSION_COLOR,\n        fill=\"none\",\n        stroke=1.8,\n    )\n    + annotate(\n        \"text\",\n        x=recession_point[\"Unemployment\"].values[0] - 0.9,\n        y=recession_point[\"Inflation\"].values[0] + 0.75,\n        label=\"2009 Recession\",\n        size=3.5,\n        fontweight=\"bold\",\n        color=RECESSION_COLOR,\n    )\n    + geom_text(\n        aes(x=\"x_label\", y=\"y_label\", label=\"Label\"),\n        data=df_labels,\n        size=3.5,\n        fontweight=\"bold\",\n        color=INK_SOFT,\n        inherit_aes=False,\n    )\n    + scale_color_gradient(\n        low=SEQ_LOW, high=SEQ_HIGH, name=\"Year\", breaks=[0, 10, 20, 30], labels=[\"1990\", \"2000\", \"2010\", \"2020\"]\n    )\n    + scale_fill_gradient(low=SEQ_LOW, high=SEQ_HIGH)\n    + scale_x_continuous(breaks=range(3, 11), expand=(0.05, 0.3))\n    + scale_y_continuous(breaks=range(-1, 7), expand=(0.05, 0.3))\n    + labs(\n        x=\"Unemployment Rate (%)\",\n        y=\"Inflation Rate (%)\",\n        title=\"scatter-connected-temporal · python · plotnine · anyplot.ai\",\n    )\n    + theme_minimal()\n    + theme(\n        figure_size=(8, 4.5),\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        plot_title=element_text(size=12, fontweight=\"bold\", color=INK),\n        legend_title=element_text(size=8, color=INK),\n        legend_text=element_text(size=7, color=INK_SOFT),\n        legend_position=\"right\",\n        legend_background=element_rect(fill=ELEVATED_BG, color=INK_SOFT),\n        plot_background=element_rect(fill=PAGE_BG, color=PAGE_BG),\n        panel_background=element_rect(fill=PAGE_BG),\n        panel_grid_major=element_line(color=INK, size=0.3, alpha=0.15),\n        panel_grid_minor=element_blank(),\n        panel_border=element_blank(),\n        axis_line=element_blank(),\n    )\n)\n\nplot.save(f\"plot-{THEME}.png\", dpi=400, width=8, height=4.5, units=\"in\", verbose=False)\n"}