{ "cells": [ { "cell_type": "markdown", "id": "45f8a36c-66e4-4ad7-b2ea-a77d176271f4", "metadata": {}, "source": [ "# Creating Magnifier Inset Effect with `ggbunch()`\n", "The `ggbunch()` here combines two plots into a single figure with custom layout - a main scatter plot showing diamond price vs. carat weight colored by cut quality, and a zoomed-in inset that magnifies a specific region of interest." ] }, { "cell_type": "code", "execution_count": 1, "id": "45afd3bd-ca54-426b-9821-73349442dced", "metadata": { "execution": { "iopub.execute_input": "2025-07-17T17:09:06.417847Z", "iopub.status.busy": "2025-07-17T17:09:06.417766Z", "iopub.status.idle": "2025-07-17T17:09:06.420664Z", "shell.execute_reply": "2025-07-17T17:09:06.420378Z" } }, "outputs": [], "source": [ "import pandas as pd\n", "\n", "from lets_plot import *" ] }, { "cell_type": "code", "execution_count": 2, "id": "3d1a30bf-a3b1-4e54-980d-e61548b55393", "metadata": { "execution": { "iopub.execute_input": "2025-07-17T17:09:06.421820Z", "iopub.status.busy": "2025-07-17T17:09:06.421485Z", "iopub.status.idle": "2025-07-17T17:09:06.423598Z", "shell.execute_reply": "2025-07-17T17:09:06.423420Z" } }, "outputs": [ { "data": { "text/html": [ "\n", "
\n", " \n", " " ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "LetsPlot.setup_html()" ] }, { "cell_type": "code", "execution_count": 3, "id": "f9ebe179-2678-4fa3-b55a-822489e3601b", "metadata": { "execution": { "iopub.execute_input": "2025-07-17T17:09:06.424382Z", "iopub.status.busy": "2025-07-17T17:09:06.424271Z", "iopub.status.idle": "2025-07-17T17:09:07.866749Z", "shell.execute_reply": "2025-07-17T17:09:07.866423Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "(53940, 10)\n" ] }, { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
caratcutcolorclaritydepthtablepricexyz
00.23IdealESI261.555.03263.953.982.43
10.21PremiumESI159.861.03263.893.842.31
20.23GoodEVS156.965.03274.054.072.31
\n", "
" ], "text/plain": [ " carat cut color clarity depth table price x y z\n", "0 0.23 Ideal E SI2 61.5 55.0 326 3.95 3.98 2.43\n", "1 0.21 Premium E SI1 59.8 61.0 326 3.89 3.84 2.31\n", "2 0.23 Good E VS1 56.9 65.0 327 4.05 4.07 2.31" ] }, "execution_count": 3, "metadata": {}, "output_type": "execute_result" } ], "source": [ "df = pd.read_csv(\"https://raw.githubusercontent.com/JetBrains/lets-plot-docs/refs/heads/master/data/diamonds.csv\")\n", "print(df.shape)\n", "df.head(3)" ] }, { "cell_type": "code", "execution_count": 4, "id": "e9a28f93-7d18-4ec1-9fc0-17edc049fe9a", "metadata": { "execution": { "iopub.execute_input": "2025-07-17T17:09:07.867799Z", "iopub.status.busy": "2025-07-17T17:09:07.867725Z", "iopub.status.idle": "2025-07-17T17:09:07.871146Z", "shell.execute_reply": "2025-07-17T17:09:07.870958Z" } }, "outputs": [], "source": [ "# Convert the 'cut' column to categorical data type with specified order\n", "cut_categories = ['Fair', 'Good', 'Very Good', 'Premium', 'Ideal']\n", "df['cut'] = pd.Categorical(df['cut'], categories=cut_categories, ordered=True)" ] }, { "cell_type": "code", "execution_count": 5, "id": "8fbb63ef-eb0c-4756-b072-19ad722182a5", "metadata": { "execution": { "iopub.execute_input": "2025-07-17T17:09:07.871996Z", "iopub.status.busy": "2025-07-17T17:09:07.871916Z", "iopub.status.idle": "2025-07-17T17:09:07.899272Z", "shell.execute_reply": "2025-07-17T17:09:07.898979Z" } }, "outputs": [], "source": [ "p_base = (ggplot(df, aes(\"carat\", \"price\", color=\"cut\"))\n", " + geom_point()\n", " + geom_smooth(deg=2, size=1, tooltips='none')\n", " + scale_color_viridis(direction = -1)\n", ")" ] }, { "cell_type": "code", "execution_count": 6, "id": "ff540616-9f5c-47d3-a4d2-4065fc9a5c07", "metadata": { "execution": { "iopub.execute_input": "2025-07-17T17:09:07.900246Z", "iopub.status.busy": "2025-07-17T17:09:07.900167Z", "iopub.status.idle": "2025-07-17T17:09:07.901655Z", "shell.execute_reply": "2025-07-17T17:09:07.901459Z" } }, "outputs": [], "source": [ "# The region of interest\n", "carat_min = 2.1\n", "carat_max = 2.7\n", "price_min = 12650\n", "price_max = 17100" ] }, { "cell_type": "code", "execution_count": 7, "id": "13096892-1744-494a-b736-3fe51d190c89", "metadata": { "execution": { "iopub.execute_input": "2025-07-17T17:09:07.902486Z", "iopub.status.busy": "2025-07-17T17:09:07.902413Z", "iopub.status.idle": "2025-07-17T17:09:08.448818Z", "shell.execute_reply": "2025-07-17T17:09:08.448485Z" } }, "outputs": [ { "data": { "text/html": [ "
\n", " " ], "text/plain": [ "" ] }, "execution_count": 7, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# The main plot\n", "p_main = (p_base\n", " + geom_rect(xmin=carat_min,\n", " xmax=carat_max,\n", " ymin=price_min,\n", " ymax=price_max,\n", " alpha=0.4, inherit_aes=False, fill='white')\n", " + theme_grey()\n", " + coord_cartesian(ylim = [0, 20000])\n", " + theme(legend_position=[0.58, 0.02], legend_justification=[0, 0])\n", ")\n", "\n", "p_main" ] }, { "cell_type": "code", "execution_count": 8, "id": "6dd05779-8947-43a1-bdfc-9e2d6871edd0", "metadata": { "execution": { "iopub.execute_input": "2025-07-17T17:09:08.452186Z", "iopub.status.busy": "2025-07-17T17:09:08.452089Z", "iopub.status.idle": "2025-07-17T17:09:09.011958Z", "shell.execute_reply": "2025-07-17T17:09:09.011649Z" } }, "outputs": [ { "data": { "text/html": [ "
\n", " " ], "text/plain": [ "" ] }, "execution_count": 8, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# The 'magnifier' plot\n", "p_mag = (p_base\n", " + theme_minimal()\n", " + coord_cartesian(xlim=[carat_min, carat_max],\n", " ylim=[price_min, price_max])\n", " + theme_void()\n", " + theme(legend_position='none', plot_inset=0)\n", ")\n", "\n", "p_mag" ] }, { "cell_type": "code", "execution_count": 9, "id": "c8f771c6-3842-4bcb-96e7-3ea8ac5502f1", "metadata": { "execution": { "iopub.execute_input": "2025-07-17T17:09:09.015116Z", "iopub.status.busy": "2025-07-17T17:09:09.015037Z", "iopub.status.idle": "2025-07-17T17:09:10.190719Z", "shell.execute_reply": "2025-07-17T17:09:10.190367Z" } }, "outputs": [ { "data": { "text/html": [ "
\n", " " ], "text/plain": [ "" ] }, "execution_count": 9, "metadata": {}, "output_type": "execute_result" } ], "source": [ "(ggbunch(\n", " plots = [\n", " (p_main\n", " + geom_segment(x=carat_min, y=price_min, xend=4.30, yend=5800, inherit_aes=False, size=0.5)\n", " + geom_segment(x=carat_min, y=price_max, xend=4.30, yend=19100, inherit_aes=False, size=0.5)\n", " ),\n", " p_mag + theme(plot_background=element_rect(size=2, fill='rgba(255, 255, 255, 0.7)'))\n", " ],\n", " regions = [\n", " (0, 0, 0.9, 1),\n", " (0.75, 0.05, 0.25, 0.6)\n", " ]\n", ") \n", " + ggsize(900, 600)\n", " + ggtitle('Diamond Price vs. Carat Weight by Cut Quality')\n", " + theme(plot_title=element_text(hjust=0.5, size=18))\n", ")" ] } ], "metadata": { "kernelspec": { "display_name": "Python 3 (ipykernel)", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.10.13" } }, "nbformat": 4, "nbformat_minor": 5 }