{"spec_id":"scatter-text","library":"altair","language":"python","code":"\"\"\" anyplot.ai\nscatter-text: Scatter Plot with Text Labels Instead of Points\nLibrary: altair 6.1.0 | Python 3.13.13\nQuality: 87/100 | Updated: 2026-05-17\n\"\"\"\n\nimport os\n\nimport numpy as np\nimport pandas as pd\nfrom altair import Chart, Color, Legend, Scale, Title, Tooltip, X, Y, condition, selection_point, value\n\n\n# Theme tokens\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\"\nBRAND = \"#009E73\"  # Okabe-Ito position 1\n\n# Data: Programming languages positioned by popularity vs age\nnp.random.seed(42)\n\nlanguages = [\n    \"Python\",\n    \"JavaScript\",\n    \"Java\",\n    \"C++\",\n    \"Ruby\",\n    \"Go\",\n    \"Rust\",\n    \"Swift\",\n    \"Kotlin\",\n    \"TypeScript\",\n    \"Scala\",\n    \"R\",\n    \"Julia\",\n    \"Perl\",\n    \"PHP\",\n    \"C#\",\n    \"Haskell\",\n    \"Elixir\",\n    \"Clojure\",\n    \"Dart\",\n    \"Lua\",\n    \"MATLAB\",\n    \"Fortran\",\n    \"COBOL\",\n    \"Lisp\",\n    \"Erlang\",\n    \"F#\",\n    \"Groovy\",\n]\n\n# Simulated: x = language age (years), y = relative popularity score\nages = np.array(\n    [33, 29, 26, 41, 29, 15, 9, 10, 13, 8, 20, 31, 12, 37, 30, 24, 34, 13, 17, 18, 31, 40, 68, 65, 66, 38, 19, 21]\n)\npopularity = np.array(\n    [98, 88, 82, 68, 42, 62, 52, 58, 48, 75, 32, 45, 28, 18, 55, 72, 12, 15, 9, 22, 25, 38, 8, 4, 6, 14, 35, 20]\n)\n\ndf = pd.DataFrame({\"age\": ages, \"popularity\": popularity, \"language\": languages, \"year_created\": 2026 - ages})\n\n# Selection for hover highlight\nhover = selection_point(on=\"pointerover\", nearest=True, empty=False)\n\nchart = (\n    Chart(df)\n    .mark_text(fontSize=14, fontWeight=\"bold\")\n    .encode(\n        x=X(\"age:Q\", title=\"Language Age (Years Since Creation)\", scale=Scale(domain=[-2, 75])),\n        y=Y(\"popularity:Q\", title=\"Relative Popularity Score\", scale=Scale(domain=[-2, 105])),\n        text=\"language:N\",\n        color=condition(\n            hover, value(BRAND), Color(\"popularity:Q\", scale=Scale(scheme=\"viridis\"), legend=Legend(title=\"Popularity\"))\n        ),\n        size=condition(hover, value(18), value(14)),\n        tooltip=[\n            Tooltip(\"language:N\", title=\"Language\"),\n            Tooltip(\"age:Q\", title=\"Age (years)\"),\n            Tooltip(\"popularity:Q\", title=\"Popularity Score\"),\n            Tooltip(\"year_created:Q\", title=\"Year Created\"),\n        ],\n    )\n    .add_params(hover)\n    .properties(\n        width=1600,\n        height=900,\n        background=PAGE_BG,\n        title=Title(text=\"scatter-text · Python · altair · anyplot.ai\", fontSize=28, anchor=\"middle\"),\n    )\n    .configure_view(fill=PAGE_BG, stroke=INK_SOFT, strokeWidth=0)\n    .configure_axis(\n        domainColor=INK_SOFT,\n        tickColor=INK_SOFT,\n        gridColor=INK,\n        gridOpacity=0.10,\n        labelColor=INK_SOFT,\n        labelFontSize=18,\n        titleColor=INK,\n        titleFontSize=22,\n    )\n    .configure_title(color=INK)\n    .configure_legend(\n        fillColor=ELEVATED_BG,\n        strokeColor=INK_SOFT,\n        labelColor=INK_SOFT,\n        titleColor=INK,\n        titleFontSize=18,\n        labelFontSize=16,\n    )\n)\n\n# Save as PNG and HTML\nchart.save(f\"plot-{THEME}.png\", scale_factor=3.0)\nchart.save(f\"plot-{THEME}.html\")\n"}