{"spec_id":"subplot-grid","library":"seaborn","language":"python","code":"\"\"\" anyplot.ai\nsubplot-grid: Subplot Grid Layout\nLibrary: seaborn 0.13.2 | Python 3.13.13\nQuality: 92/100 | Updated: 2026-05-13\n\"\"\"\n\nimport os\n\nimport matplotlib.pyplot as plt\nimport numpy as np\nimport pandas as pd\nimport seaborn as sns\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\nIMPRINT = [\"#009E73\", \"#C475FD\", \"#4467A3\", \"#BD8233\", \"#AE3030\", \"#2ABCCD\", \"#954477\"]\n\n# Apply theme to seaborn\nsns.set_theme(\n    style=\"ticks\",\n    rc={\n        \"figure.facecolor\": PAGE_BG,\n        \"axes.facecolor\": PAGE_BG,\n        \"axes.edgecolor\": INK_SOFT,\n        \"axes.labelcolor\": INK,\n        \"text.color\": INK,\n        \"xtick.color\": INK_SOFT,\n        \"ytick.color\": INK_SOFT,\n        \"grid.color\": INK,\n        \"grid.alpha\": 0.10,\n        \"legend.facecolor\": ELEVATED_BG,\n        \"legend.edgecolor\": INK_SOFT,\n    },\n)\n\n# Data - Environmental monitoring scenario\nnp.random.seed(42)\n\n# Time series: 48 hours of hourly readings\nhours = np.arange(48)\ndates = pd.date_range(\"2024-03-15\", periods=48, freq=\"h\")\n\n# Temperature readings (Celsius) - realistic pattern with daily cycle\nbase_temp = 15 + 8 * np.sin(np.pi * hours / 24)\ntemperature = base_temp + np.random.normal(0, 0.8, 48)\n\n# Humidity readings (%)\nbase_humidity = 60 + 15 * np.sin(np.pi * (hours - 6) / 24)\nhumidity = base_humidity + np.random.normal(0, 3, 48)\n\n# Air quality index (AQI)\naqi = 40 + 20 * np.abs(np.sin(np.pi * hours / 48)) + np.random.normal(0, 2, 48)\n\n# Pressure readings (hPa)\npressure = 1013 + np.cumsum(np.random.normal(0, 0.1, 48))\n\n# Create DataFrame\ndf = pd.DataFrame(\n    {\n        \"Hour\": hours,\n        \"DateTime\": dates,\n        \"Temperature\": temperature,\n        \"Humidity\": humidity,\n        \"AQI\": aqi,\n        \"Pressure\": pressure,\n    }\n)\n\n# Create 2x2 subplot grid\nfig, axes = plt.subplots(2, 2, figsize=(16, 9), facecolor=PAGE_BG)\n\n# Subplot 1: Temperature Time Series (top-left)\nax1 = axes[0, 0]\nsns.lineplot(data=df, x=\"Hour\", y=\"Temperature\", ax=ax1, color=IMPRINT[0], linewidth=3)\nax1.set_title(\"Temperature Over Time\", fontsize=24, fontweight=\"medium\", color=INK)\nax1.set_xlabel(\"Hours Since Start\", fontsize=20, color=INK)\nax1.set_ylabel(\"Temperature (°C)\", fontsize=20, color=INK)\nax1.tick_params(axis=\"both\", labelsize=16, colors=INK_SOFT)\nax1.spines[\"top\"].set_visible(False)\nax1.spines[\"right\"].set_visible(False)\nax1.yaxis.grid(True, alpha=0.10, linewidth=0.8, color=INK)\n\n# Subplot 2: Humidity Distribution (top-right)\nax2 = axes[0, 1]\nsns.histplot(data=df, x=\"Humidity\", bins=15, ax=ax2, color=IMPRINT[1], alpha=0.7, edgecolor=PAGE_BG)\nax2.set_title(\"Humidity Distribution\", fontsize=24, fontweight=\"medium\", color=INK)\nax2.set_xlabel(\"Humidity (%)\", fontsize=20, color=INK)\nax2.set_ylabel(\"Frequency\", fontsize=20, color=INK)\nax2.tick_params(axis=\"both\", labelsize=16, colors=INK_SOFT)\nax2.spines[\"top\"].set_visible(False)\nax2.spines[\"right\"].set_visible(False)\nax2.yaxis.grid(True, alpha=0.10, linewidth=0.8, color=INK)\n\n# Subplot 3: Temperature vs Humidity Scatter (bottom-left)\nax3 = axes[1, 0]\nsns.scatterplot(\n    data=df,\n    x=\"Temperature\",\n    y=\"Humidity\",\n    hue=\"Hour\",\n    palette=\"viridis\",\n    s=150,\n    alpha=0.8,\n    ax=ax3,\n    edgecolor=PAGE_BG,\n    linewidth=0.5,\n)\nax3.set_title(\"Temperature vs Humidity\", fontsize=24, fontweight=\"medium\", color=INK)\nax3.set_xlabel(\"Temperature (°C)\", fontsize=20, color=INK)\nax3.set_ylabel(\"Humidity (%)\", fontsize=20, color=INK)\nax3.tick_params(axis=\"both\", labelsize=16, colors=INK_SOFT)\nax3.spines[\"top\"].set_visible(False)\nax3.spines[\"right\"].set_visible(False)\nax3.grid(True, alpha=0.10, linewidth=0.8, color=INK)\nax3.legend(title=\"Hour\", fontsize=12, title_fontsize=13, loc=\"best\")\n\n# Subplot 4: Air Quality and Pressure (bottom-right)\nax4 = axes[1, 1]\nax4_twin = ax4.twinx()\n\n# Plot AQI as bars\nbars = ax4.bar(\n    df[\"Hour\"], df[\"AQI\"], alpha=0.6, color=IMPRINT[2], label=\"AQI\", width=0.8, edgecolor=PAGE_BG, linewidth=0.5\n)\n\n# Plot Pressure as line on twin axis\nline = ax4_twin.plot(\n    df[\"Hour\"], df[\"Pressure\"], color=IMPRINT[3], linewidth=3, marker=\"o\", markersize=6, label=\"Pressure\"\n)\n\nax4.set_title(\"Air Quality & Pressure\", fontsize=24, fontweight=\"medium\", color=INK)\nax4.set_xlabel(\"Hours Since Start\", fontsize=20, color=INK)\nax4.set_ylabel(\"AQI\", fontsize=20, color=INK)\nax4_twin.set_ylabel(\"Pressure (hPa)\", fontsize=20, color=INK)\n\nax4.tick_params(axis=\"both\", labelsize=16, colors=INK_SOFT)\nax4_twin.tick_params(axis=\"y\", labelsize=16, colors=INK_SOFT)\nax4.spines[\"top\"].set_visible(False)\nax4_twin.spines[\"top\"].set_visible(False)\nax4.yaxis.grid(True, alpha=0.10, linewidth=0.8, color=INK)\n\n# Combined legend\nlines1, labels1 = ax4.get_legend_handles_labels()\nlines2, labels2 = ax4_twin.get_legend_handles_labels()\nax4.legend(lines1 + lines2, labels1 + labels2, fontsize=14, loc=\"upper left\")\n\n# Main title\nfig.suptitle(\"subplot-grid · seaborn · anyplot.ai\", fontsize=24, fontweight=\"medium\", color=INK, y=0.98)\n\nplt.tight_layout(rect=[0, 0, 1, 0.95])\nplt.savefig(f\"plot-{THEME}.png\", dpi=300, bbox_inches=\"tight\", facecolor=PAGE_BG)\n"}