Download notebook (.ipynb)

Lollipop Plot#

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.

import numpy as np
import pandas as pd

from lets_plot import *
LetsPlot.setup_html()
def get_lollipop_data(size, seed=42):
    np.random.seed(seed)
    return {
        "x": [v - 15 for v in range(size)],
        "y": np.random.uniform(1, 5, size=size),
        "sugar": [v + 150 for v in range(size)]
    }

data = get_lollipop_data(30)
ggplot(data, aes("x", "y")) + geom_lollipop() + ggsize(600, 200)

1. Parameters size, stroke and linewidth#

gggrid([
    ggplot(data, aes("x", "y", size="sugar")) + \
        geom_lollipop() + \
        ggtitle("variable 'size'"),
    ggplot(data, aes("x", "y", size="sugar", stroke="sugar")) + \
        geom_lollipop() + \
        ggtitle("variable 'size' and 'stroke'"),
    ggplot(data, aes("x", "y", size="sugar", linewidth="sugar")) + \
        geom_lollipop() + \
        ggtitle("variable 'size' and 'linewidth'")
], ncol=1) + ggsize(800, 800)

2. Parameter fatten#

gggrid([
    ggplot(data, aes("x", "y")) + geom_lollipop() + ggtitle("fatten=2.5 (default)"),
    ggplot(data, aes("x", "y")) + geom_lollipop(fatten=5) + ggtitle("fatten=5"),
])

3. Horizontal Sticks#

ggplot(data, aes("y", "x")) + geom_lollipop(dir='h')

4. Sloped Baseline#

slope = .5
intercept = 1

abline_plot = ggplot(data, aes("x", "y")) + \
    geom_abline(intercept=intercept, slope=slope, color="black", linetype='dotted', size=1.5) + \
    coord_fixed(ylim=[-12, 12])

gggrid([
    abline_plot + geom_lollipop(intercept=intercept, slope=slope, shape=21) + ggtitle("dir='v' (default)"),
    abline_plot + geom_lollipop(intercept=intercept, slope=slope, shape=21, dir='h') + ggtitle("dir='h'"),
    abline_plot + geom_lollipop(intercept=intercept, slope=slope, shape=21, dir='s') + ggtitle("dir='s'"),
])

5. Parameter stat#

df = pd.read_csv("https://raw.githubusercontent.com/JetBrains/lets-plot-docs/master/data/mpg.csv")
print(df.shape)
df.head()
(234, 12)
Unnamed: 0 manufacturer model displ year cyl trans drv cty hwy fl class
0 1 audi a4 1.8 1999 4 auto(l5) f 18 29 p compact
1 2 audi a4 1.8 1999 4 manual(m5) f 21 29 p compact
2 3 audi a4 2.0 2008 4 manual(m6) f 20 31 p compact
3 4 audi a4 2.0 2008 4 auto(av) f 21 30 p compact
4 5 audi a4 2.8 1999 6 auto(l5) f 16 26 p compact
gggrid([
    ggplot(df, aes(x="class")) + geom_lollipop(stat='count') + ggtitle("stat='count'"),
    ggplot(df, aes(x="hwy")) + geom_lollipop(stat='bin') + ggtitle("stat='bin'"),
    ggplot(df, aes(x="hwy")) + geom_lollipop(stat='density', n=30) + ggtitle("stat='density'"),
])

6. Lollipops in Marginal Layer#

ggplot(df, aes("hwy", "cty")) + \
    geom_bin2d(binwidth=[1, 1]) + \
    ggmarginal("r", size=.2, \
               layer=geom_lollipop(aes(color="..count.."), \
                                   stat='count', orientation='y', size=1))

7. Lollipops and a Regression Line#

from sklearn.linear_model import LinearRegression
model = LinearRegression().fit(df[["hwy"]], df["cty"])
slope, intercept = model.coef_[0], model.intercept_

ggplot(df, aes("hwy", "cty")) + \
    geom_smooth(level=.99, seed=42) + \
    geom_lollipop(slope=slope, intercept=intercept, \
                  size=1.2, shape=21, color="black", fill="magenta") + \
    coord_fixed()