{ "cells": [ { "cell_type": "markdown", "id": "bbf78031", "metadata": {}, "source": [ "# Lollipop Plot\n", "\n", "A lollipop plot displays each element of a dataset as a segment and a circle. It is usually combined with the `count` stat, and is especially useful when you have several bars of the same height." ] }, { "cell_type": "code", "execution_count": 1, "id": "4e5f30b9", "metadata": { "execution": { "iopub.execute_input": "2026-01-27T17:06:13.899236Z", "iopub.status.busy": "2026-01-27T17:06:13.899161Z", "iopub.status.idle": "2026-01-27T17:06:13.902045Z", "shell.execute_reply": "2026-01-27T17:06:13.901710Z" } }, "outputs": [], "source": [ "import numpy as np\n", "import pandas as pd\n", "\n", "from lets_plot import *" ] }, { "cell_type": "code", "execution_count": 2, "id": "aca5e584", "metadata": { "execution": { "iopub.execute_input": "2026-01-27T17:06:13.902877Z", "iopub.status.busy": "2026-01-27T17:06:13.902802Z", "iopub.status.idle": "2026-01-27T17:06:13.904613Z", "shell.execute_reply": "2026-01-27T17:06:13.904357Z" } }, "outputs": [ { "data": { "text/html": [ "\n", "
\n", " \n", " " ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "LetsPlot.setup_html()" ] }, { "cell_type": "code", "execution_count": 3, "id": "1a13082d", "metadata": { "execution": { "iopub.execute_input": "2026-01-27T17:06:13.905602Z", "iopub.status.busy": "2026-01-27T17:06:13.905533Z", "iopub.status.idle": "2026-01-27T17:06:13.907384Z", "shell.execute_reply": "2026-01-27T17:06:13.907108Z" } }, "outputs": [], "source": [ "def get_lollipop_data(size, seed=42):\n", " np.random.seed(seed)\n", " return {\n", " \"x\": [v - 15 for v in range(size)],\n", " \"y\": np.random.uniform(1, 5, size=size),\n", " \"sugar\": [v + 150 for v in range(size)]\n", " }\n", "\n", "data = get_lollipop_data(30)" ] }, { "cell_type": "code", "execution_count": 4, "id": "fd78698e", "metadata": { "execution": { "iopub.execute_input": "2026-01-27T17:06:13.908454Z", "iopub.status.busy": "2026-01-27T17:06:13.908384Z", "iopub.status.idle": "2026-01-27T17:06:13.947606Z", "shell.execute_reply": "2026-01-27T17:06:13.947186Z" } }, "outputs": [ { "data": { "text/html": [ "
\n", " " ], "text/plain": [ "" ] }, "execution_count": 4, "metadata": {}, "output_type": "execute_result" } ], "source": [ "ggplot(data, aes(\"x\", \"y\")) + geom_lollipop() + ggsize(600, 200)" ] }, { "cell_type": "markdown", "id": "79609dc2", "metadata": {}, "source": [ "#### 1. Parameters `size`, `stroke` and `linewidth`" ] }, { "cell_type": "code", "execution_count": 5, "id": "5bdea834", "metadata": { "execution": { "iopub.execute_input": "2026-01-27T17:06:13.948616Z", "iopub.status.busy": "2026-01-27T17:06:13.948537Z", "iopub.status.idle": "2026-01-27T17:06:13.952930Z", "shell.execute_reply": "2026-01-27T17:06:13.952642Z" } }, "outputs": [ { "data": { "text/html": [ "
\n", " " ], "text/plain": [ "" ] }, "execution_count": 5, "metadata": {}, "output_type": "execute_result" } ], "source": [ "gggrid([\n", " ggplot(data, aes(\"x\", \"y\", size=\"sugar\")) + \\\n", " geom_lollipop() + \\\n", " ggtitle(\"variable 'size'\"),\n", " ggplot(data, aes(\"x\", \"y\", size=\"sugar\", stroke=\"sugar\")) + \\\n", " geom_lollipop() + \\\n", " ggtitle(\"variable 'size' and 'stroke'\"),\n", " ggplot(data, aes(\"x\", \"y\", size=\"sugar\", linewidth=\"sugar\")) + \\\n", " geom_lollipop() + \\\n", " ggtitle(\"variable 'size' and 'linewidth'\")\n", "], ncol=1) + ggsize(800, 800)" ] }, { "cell_type": "markdown", "id": "d72102d6", "metadata": {}, "source": [ "#### 2. Parameter `fatten`" ] }, { "cell_type": "code", "execution_count": 6, "id": "a68c6d9c", "metadata": { "execution": { "iopub.execute_input": "2026-01-27T17:06:13.953869Z", "iopub.status.busy": "2026-01-27T17:06:13.953802Z", "iopub.status.idle": "2026-01-27T17:06:13.957474Z", "shell.execute_reply": "2026-01-27T17:06:13.957181Z" } }, "outputs": [ { "data": { "text/html": [ "
\n", " " ], "text/plain": [ "" ] }, "execution_count": 6, "metadata": {}, "output_type": "execute_result" } ], "source": [ "gggrid([\n", " ggplot(data, aes(\"x\", \"y\")) + geom_lollipop() + ggtitle(\"fatten=2.5 (default)\"),\n", " ggplot(data, aes(\"x\", \"y\")) + geom_lollipop(fatten=5) + ggtitle(\"fatten=5\"),\n", "])" ] }, { "cell_type": "markdown", "id": "de1e9b3f", "metadata": {}, "source": [ "#### 3. Horizontal Sticks" ] }, { "cell_type": "code", "execution_count": 7, "id": "d5d35123", "metadata": { "execution": { "iopub.execute_input": "2026-01-27T17:06:13.958399Z", "iopub.status.busy": "2026-01-27T17:06:13.958310Z", "iopub.status.idle": "2026-01-27T17:06:13.961022Z", "shell.execute_reply": "2026-01-27T17:06:13.960751Z" } }, "outputs": [ { "data": { "text/html": [ "
\n", " " ], "text/plain": [ "" ] }, "execution_count": 7, "metadata": {}, "output_type": "execute_result" } ], "source": [ "ggplot(data, aes(\"y\", \"x\")) + geom_lollipop(dir='h')" ] }, { "cell_type": "markdown", "id": "3e276f0f", "metadata": {}, "source": [ "#### 4. Sloped Baseline" ] }, { "cell_type": "code", "execution_count": 8, "id": "409caaf3", "metadata": { "execution": { "iopub.execute_input": "2026-01-27T17:06:13.961889Z", "iopub.status.busy": "2026-01-27T17:06:13.961821Z", "iopub.status.idle": "2026-01-27T17:06:13.966894Z", "shell.execute_reply": "2026-01-27T17:06:13.966571Z" } }, "outputs": [ { "data": { "text/html": [ "
\n", " " ], "text/plain": [ "" ] }, "execution_count": 8, "metadata": {}, "output_type": "execute_result" } ], "source": [ "slope = .5\n", "intercept = 1\n", "\n", "abline_plot = ggplot(data, aes(\"x\", \"y\")) + \\\n", " geom_abline(intercept=intercept, slope=slope, color=\"black\", linetype='dotted', size=1.5) + \\\n", " coord_fixed(ylim=[-12, 12])\n", "\n", "gggrid([\n", " abline_plot + geom_lollipop(intercept=intercept, slope=slope, shape=21) + ggtitle(\"dir='v' (default)\"),\n", " abline_plot + geom_lollipop(intercept=intercept, slope=slope, shape=21, dir='h') + ggtitle(\"dir='h'\"),\n", " abline_plot + geom_lollipop(intercept=intercept, slope=slope, shape=21, dir='s') + ggtitle(\"dir='s'\"),\n", "])" ] }, { "cell_type": "markdown", "id": "3bd40d9f", "metadata": {}, "source": [ "#### 5. Parameter `stat`" ] }, { "cell_type": "code", "execution_count": 9, "id": "0fc4c215", "metadata": { "execution": { "iopub.execute_input": "2026-01-27T17:06:13.967906Z", "iopub.status.busy": "2026-01-27T17:06:13.967835Z", "iopub.status.idle": "2026-01-27T17:06:14.065151Z", "shell.execute_reply": "2026-01-27T17:06:14.064801Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "(234, 12)\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", " \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", "
Unnamed: 0manufacturermodeldisplyearcyltransdrvctyhwyflclass
01audia41.819994auto(l5)f1829pcompact
12audia41.819994manual(m5)f2129pcompact
23audia42.020084manual(m6)f2031pcompact
34audia42.020084auto(av)f2130pcompact
45audia42.819996auto(l5)f1626pcompact
\n", "
" ], "text/plain": [ " Unnamed: 0 manufacturer model displ year cyl trans drv cty hwy \\\n", "0 1 audi a4 1.8 1999 4 auto(l5) f 18 29 \n", "1 2 audi a4 1.8 1999 4 manual(m5) f 21 29 \n", "2 3 audi a4 2.0 2008 4 manual(m6) f 20 31 \n", "3 4 audi a4 2.0 2008 4 auto(av) f 21 30 \n", "4 5 audi a4 2.8 1999 6 auto(l5) f 16 26 \n", "\n", " fl class \n", "0 p compact \n", "1 p compact \n", "2 p compact \n", "3 p compact \n", "4 p compact " ] }, "execution_count": 9, "metadata": {}, "output_type": "execute_result" } ], "source": [ "df = pd.read_csv(\"https://raw.githubusercontent.com/JetBrains/lets-plot-docs/master/data/mpg.csv\")\n", "print(df.shape)\n", "df.head()" ] }, { "cell_type": "code", "execution_count": 10, "id": "341237ee", "metadata": { "execution": { "iopub.execute_input": "2026-01-27T17:06:14.066293Z", "iopub.status.busy": "2026-01-27T17:06:14.066221Z", "iopub.status.idle": "2026-01-27T17:06:14.077227Z", "shell.execute_reply": "2026-01-27T17:06:14.076950Z" } }, "outputs": [ { "data": { "text/html": [ "
\n", " " ], "text/plain": [ "" ] }, "execution_count": 10, "metadata": {}, "output_type": "execute_result" } ], "source": [ "gggrid([\n", " ggplot(df, aes(x=\"class\")) + geom_lollipop(stat='count') + ggtitle(\"stat='count'\"),\n", " ggplot(df, aes(x=\"hwy\")) + geom_lollipop(stat='bin') + ggtitle(\"stat='bin'\"),\n", " ggplot(df, aes(x=\"hwy\")) + geom_lollipop(stat='density', n=30) + ggtitle(\"stat='density'\"),\n", "])" ] }, { "cell_type": "markdown", "id": "932bd637", "metadata": {}, "source": [ "#### 6. Lollipops in Marginal Layer" ] }, { "cell_type": "code", "execution_count": 11, "id": "14b8ff38", "metadata": { "execution": { "iopub.execute_input": "2026-01-27T17:06:14.078368Z", "iopub.status.busy": "2026-01-27T17:06:14.078298Z", "iopub.status.idle": "2026-01-27T17:06:14.084038Z", "shell.execute_reply": "2026-01-27T17:06:14.083764Z" } }, "outputs": [ { "data": { "text/html": [ "
\n", " " ], "text/plain": [ "" ] }, "execution_count": 11, "metadata": {}, "output_type": "execute_result" } ], "source": [ "ggplot(df, aes(\"hwy\", \"cty\")) + \\\n", " geom_bin2d(binwidth=[1, 1]) + \\\n", " ggmarginal(\"r\", size=.2, \\\n", " layer=geom_lollipop(aes(color=\"..count..\"), \\\n", " stat='count', orientation='y', size=1))" ] }, { "cell_type": "markdown", "id": "1405210e", "metadata": {}, "source": [ "#### 7. Lollipops and a Regression Line" ] }, { "cell_type": "code", "execution_count": 12, "id": "7f4d3de1-48ca-472b-83d5-c2077818732c", "metadata": { "execution": { "iopub.execute_input": "2026-01-27T17:06:14.084992Z", "iopub.status.busy": "2026-01-27T17:06:14.084920Z", "iopub.status.idle": "2026-01-27T17:06:14.295030Z", "shell.execute_reply": "2026-01-27T17:06:14.294474Z" } }, "outputs": [], "source": [ "from sklearn.linear_model import LinearRegression" ] }, { "cell_type": "code", "execution_count": 13, "id": "f14b6636", "metadata": { "execution": { "iopub.execute_input": "2026-01-27T17:06:14.296416Z", "iopub.status.busy": "2026-01-27T17:06:14.296257Z", "iopub.status.idle": "2026-01-27T17:06:14.303956Z", "shell.execute_reply": "2026-01-27T17:06:14.303724Z" } }, "outputs": [ { "data": { "text/html": [ "
\n", " " ], "text/plain": [ "" ] }, "execution_count": 13, "metadata": {}, "output_type": "execute_result" } ], "source": [ "model = LinearRegression().fit(df[[\"hwy\"]], df[\"cty\"])\n", "slope, intercept = model.coef_[0], model.intercept_\n", "\n", "ggplot(df, aes(\"hwy\", \"cty\")) + \\\n", " geom_smooth(level=.99, seed=42) + \\\n", " geom_lollipop(slope=slope, intercept=intercept, \\\n", " size=1.2, shape=21, color=\"black\", fill=\"magenta\") + \\\n", " coord_fixed()" ] } ], "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 }