{"spec_id":"scatter-matrix","library":"plotnine","language":"python","code":"\"\"\" anyplot.ai\nscatter-matrix: Scatter Plot Matrix\nLibrary: plotnine 0.15.4 | Python 3.13.13\nQuality: 94/100 | Updated: 2026-05-09\n\"\"\"\n\nimport os\n\nimport numpy as np\nimport pandas as pd\nfrom plotnine import (\n    aes,\n    element_blank,\n    element_line,\n    element_rect,\n    element_text,\n    facet_grid,\n    geom_density,\n    geom_point,\n    ggplot,\n    labs,\n    scale_color_manual,\n    scale_fill_manual,\n    theme,\n    theme_minimal,\n)\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\"\n\n# Okabe-Ito palette (first series always #009E73)\nIMPRINT = [\"#009E73\", \"#C475FD\", \"#4467A3\"]\n\n# Data - Iris-like data for multivariate visualization\nnp.random.seed(42)\n\nspecies = np.repeat([\"setosa\", \"versicolor\", \"virginica\"], 50)\n\ndata = {\n    \"Sepal Length (cm)\": np.concatenate(\n        [np.random.normal(5.0, 0.35, 50), np.random.normal(5.9, 0.5, 50), np.random.normal(6.6, 0.6, 50)]\n    ),\n    \"Sepal Width (cm)\": np.concatenate(\n        [np.random.normal(3.4, 0.4, 50), np.random.normal(2.8, 0.3, 50), np.random.normal(3.0, 0.3, 50)]\n    ),\n    \"Petal Length (cm)\": np.concatenate(\n        [np.random.normal(1.5, 0.2, 50), np.random.normal(4.3, 0.5, 50), np.random.normal(5.5, 0.5, 50)]\n    ),\n    \"Petal Width (cm)\": np.concatenate(\n        [np.random.normal(0.25, 0.1, 50), np.random.normal(1.3, 0.2, 50), np.random.normal(2.0, 0.3, 50)]\n    ),\n    \"Species\": species,\n}\n\ndf = pd.DataFrame(data)\n\nvariables = [\"Sepal Length (cm)\", \"Sepal Width (cm)\", \"Petal Length (cm)\", \"Petal Width (cm)\"]\n\n# Create long-form data for faceted scatter matrix\nscatter_data = []\nfor var_y in variables:\n    for var_x in variables:\n        for idx in range(len(df)):\n            scatter_data.append(\n                {\n                    \"x\": df[var_x].iloc[idx],\n                    \"y\": df[var_y].iloc[idx],\n                    \"var_x\": var_x,\n                    \"var_y\": var_y,\n                    \"Species\": df[\"Species\"].iloc[idx],\n                    \"is_diag\": var_x == var_y,\n                }\n            )\n\nplot_df = pd.DataFrame(scatter_data)\n\n# Set categorical type with explicit order for consistent row/column ordering\nplot_df[\"var_x\"] = pd.Categorical(plot_df[\"var_x\"], categories=variables, ordered=True)\nplot_df[\"var_y\"] = pd.Categorical(plot_df[\"var_y\"], categories=variables, ordered=True)\n\nscatter_df = plot_df[~plot_df[\"is_diag\"]]\ndiag_df = plot_df[plot_df[\"is_diag\"]]\n\n# Theme-adaptive styling\nanyplot_theme = theme(\n    figure_size=(14, 14),\n    plot_background=element_rect(fill=PAGE_BG, color=PAGE_BG),\n    panel_background=element_rect(fill=PAGE_BG, color=PAGE_BG),\n    panel_grid_major=element_line(color=INK, size=0.3, alpha=0.10),\n    panel_grid_minor=element_blank(),\n    panel_border=element_rect(color=INK_SOFT, fill=None, size=0.4),\n    axis_title=element_text(size=20, color=INK),\n    axis_text=element_text(size=16, color=INK_SOFT),\n    axis_line=element_line(color=INK_SOFT, size=0.4),\n    axis_ticks=element_line(color=INK_SOFT, size=0.3),\n    plot_title=element_text(size=22, face=\"bold\", ha=\"center\", color=INK),\n    strip_text_x=element_text(size=13, face=\"bold\", color=INK),\n    strip_text_y=element_text(size=13, face=\"bold\", angle=0, color=INK),\n    legend_background=element_rect(fill=ELEVATED_BG, color=INK_SOFT, size=0.4),\n    legend_text=element_text(size=13, color=INK_SOFT),\n    legend_title=element_text(size=14, color=INK),\n    legend_position=\"right\",\n    panel_spacing=0.12,\n    axis_title_x=element_blank(),\n    axis_title_y=element_blank(),\n)\n\n# Create scatter matrix using facet_grid\nplot = (\n    ggplot(scatter_df, aes(x=\"x\", y=\"y\", color=\"Species\"))\n    + geom_point(size=3.5, alpha=0.7)\n    + geom_density(aes(x=\"x\", fill=\"Species\", color=\"Species\"), data=diag_df, alpha=0.4)\n    + facet_grid(\"var_y ~ var_x\", scales=\"free\", labeller=\"label_value\")\n    + scale_color_manual(values=IMPRINT)\n    + scale_fill_manual(values=IMPRINT)\n    + labs(title=\"scatter-matrix · plotnine · anyplot.ai\", x=\"\", y=\"\")\n    + theme_minimal()\n    + anyplot_theme\n)\n\n# Save the plot\nplot.save(f\"plot-{THEME}.png\", dpi=300, width=14, height=14, verbose=False)\n"}