{"spec_id":"subplot-mosaic","library":"letsplot","language":"python","code":"\"\"\" anyplot.ai\nsubplot-mosaic: Mosaic Subplot Layout with Varying Sizes\nLibrary: letsplot 4.9.0 | Python 3.13.13\nQuality: 89/100 | Updated: 2026-05-14\n\"\"\"\n\nimport os\n\nimport numpy as np\nimport pandas as pd\nfrom lets_plot import *\n\n\nLetsPlot.setup_html()\n\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\nIMPRINT = [\"#009E73\", \"#C475FD\", \"#4467A3\", \"#BD8233\", \"#AE3030\", \"#2ABCCD\", \"#954477\"]\n\nnp.random.seed(42)\n\n# Panel A: Wide time series overview (top - spans full width)\ndates = pd.date_range(\"2024-01-01\", periods=100, freq=\"D\")\nrevenue = np.cumsum(np.random.randn(100) * 10 + 5) + 1000\ndf_overview = pd.DataFrame({\"date\": dates, \"revenue\": revenue})\ndf_overview[\"day_num\"] = range(len(df_overview))\n\n# Panel B: Bar chart data (middle left - large panel)\ncategories = [\"Product A\", \"Product B\", \"Product C\", \"Product D\", \"Product E\"]\nsales = [450, 380, 290, 520, 340]\ndf_bar = pd.DataFrame({\"category\": categories, \"sales\": sales})\n\n# Panel C: Scatter data (middle right)\nx_scatter = np.random.uniform(20, 80, 60)\ny_scatter = x_scatter * 0.7 + np.random.randn(60) * 8 + 10\ndf_scatter = pd.DataFrame({\"effort\": x_scatter, \"output\": y_scatter})\n\n# Panel D: Histogram data (bottom left)\nvalues = np.concatenate([np.random.normal(50, 10, 150), np.random.normal(80, 8, 100)])\ndf_hist = pd.DataFrame({\"metric\": values})\n\n# Panel E: Line chart data (bottom middle)\nmonths = [\"Jan\", \"Feb\", \"Mar\", \"Apr\", \"May\", \"Jun\"]\ngrowth = [2.1, 3.5, 2.8, 4.2, 3.9, 5.1]\ndf_line = pd.DataFrame({\"month\": months, \"growth\": growth})\ndf_line[\"month_num\"] = range(len(df_line))\n\n# Panel F: Heatmap data (bottom right - with some empty notation)\nmatrix_data = []\nfor row_label in [\"Q1\", \"Q2\", \"Q3\", \"Q4\"]:\n    for col_label in [\"Region A\", \"Region B\", \"Region C\"]:\n        value = int(np.random.uniform(60, 100))\n        matrix_data.append({\"quarter\": row_label, \"region\": col_label, \"value\": value})\ndf_heatmap = pd.DataFrame(matrix_data)\n\n# Theme configuration\nbase_theme = theme_minimal() + theme(\n    axis_title=element_text(size=20, color=INK),\n    axis_text=element_text(size=16, color=INK_SOFT),\n    plot_title=element_text(size=22, face=\"bold\", color=INK),\n    panel_background=element_rect(fill=PAGE_BG, color=PAGE_BG),\n    plot_background=element_rect(fill=PAGE_BG, color=PAGE_BG),\n    panel_grid_major=element_line(color=INK_SOFT, size=0.2),\n    panel_grid_minor=element_blank(),\n    legend_background=element_rect(fill=ELEVATED_BG, color=INK_SOFT),\n    legend_text=element_text(color=INK_SOFT),\n    legend_title=element_text(color=INK),\n)\n\n# Panel A: Wide time series (top, spans all 3 columns)\nplot_a = (\n    ggplot(df_overview, aes(\"day_num\", \"revenue\"))\n    + geom_area(fill=IMPRINT[0], alpha=0.3)\n    + geom_line(color=IMPRINT[0], size=2)\n    + labs(x=\"Day\", y=\"Revenue ($)\", title=\"Daily Revenue Overview\")\n    + base_theme\n)\n\n# Panel B: Bar chart (middle row, spans 2/3 width)\nplot_b = (\n    ggplot(df_bar, aes(\"category\", \"sales\"))\n    + geom_bar(stat=\"identity\", fill=IMPRINT[0], color=INK_SOFT, size=0.6, alpha=0.85)\n    + labs(x=\"Product Category\", y=\"Units Sold\", title=\"Sales by Product\")\n    + base_theme\n    + theme(axis_text_x=element_text(angle=45, hjust=1))\n)\n\n# Panel C: Scatter plot (middle row, 1/3 width)\nplot_c = (\n    ggplot(df_scatter, aes(\"effort\", \"output\"))\n    + geom_point(color=IMPRINT[0], size=6, alpha=0.7, fill=IMPRINT[0])\n    + geom_smooth(method=\"lm\", color=IMPRINT[1], size=1.5, se=False)\n    + labs(x=\"Effort (hours)\", y=\"Output (units)\", title=\"Effort vs Output\")\n    + base_theme\n)\n\n# Panel D: Histogram (bottom left)\nplot_d = (\n    ggplot(df_hist, aes(\"metric\"))\n    + geom_histogram(bins=25, fill=IMPRINT[0], color=INK_SOFT, alpha=0.8, size=0.3)\n    + labs(x=\"Performance Score\", y=\"Frequency\", title=\"Score Distribution\")\n    + base_theme\n)\n\n# Panel E: Line chart with points (bottom middle)\nplot_e = (\n    ggplot(df_line, aes(\"month_num\", \"growth\"))\n    + geom_line(color=IMPRINT[0], size=2.5)\n    + geom_point(color=IMPRINT[0], size=8, fill=IMPRINT[0], alpha=0.8)\n    + scale_x_continuous(breaks=list(range(6)), labels=months)\n    + labs(x=\"Month\", y=\"Growth Rate (%)\", title=\"Monthly Growth\")\n    + base_theme\n)\n\n# Panel F: Heatmap (bottom right)\nplot_f = (\n    ggplot(df_heatmap, aes(\"region\", \"quarter\", fill=\"value\"))\n    + geom_tile(color=INK_SOFT, size=1)\n    + geom_text(aes(label=\"value\"), format=\".0f\", size=14, color=INK)\n    + scale_fill_viridis(name=\"Value\")\n    + labs(x=\"Region\", y=\"Quarter\", title=\"Regional Performance\")\n    + base_theme\n    + theme(legend_position=\"right\", legend_text=element_text(size=14))\n)\n\n# Create mosaic layout using ggbunch with regions\n# AAA (top - full width)\n# BBC (middle - B spans 2/3, C spans 1/3)\n# DEF (bottom - three equal panels)\nfinal_plot = ggbunch(\n    plots=[plot_a, plot_b, plot_c, plot_d, plot_e, plot_f],\n    regions=[\n        (0, 0, 1.0, 0.22),\n        (0, 0.24, 0.65, 0.38),\n        (0.67, 0.24, 0.33, 0.38),\n        (0, 0.64, 0.32, 0.36),\n        (0.34, 0.64, 0.32, 0.36),\n        (0.68, 0.64, 0.32, 0.36),\n    ],\n) + ggsize(1600, 900)\n\noutput_dir = os.path.dirname(os.path.abspath(__file__))\n\n# Add centered title to the plot\nfinal_plot_with_title = (\n    final_plot\n    + ggtitle(\"subplot-mosaic · letsplot · anyplot.ai\")\n    + theme(plot_title=element_text(size=26, color=INK, face=\"bold\", hjust=0.5))\n)\n\nggsave(final_plot_with_title, os.path.join(output_dir, f\"plot-{THEME}.png\"), scale=3)\nggsave(final_plot_with_title, os.path.join(output_dir, f\"plot-{THEME}.html\"))\n"}