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.

In [1]:
import random
import pandas as pd
from sklearn.linear_model import LinearRegression

from lets_plot import *
In [2]:
LetsPlot.setup_html()
In [3]:
random.seed(42)
data = {
    'x': [v - 15 for v in range(30)],
    'y': [random.uniform(1, 5) for _ in range(30)],
    'sugar': [v + 150 for v in range(30)]
}
In [4]:
ggplot(data, aes('x', 'y')) + geom_lollipop() + ggsize(600, 200)
Out[4]:

1. Parameters size, stroke and linewidth

In [5]:
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)
Out[5]:

2. Parameter fatten

In [6]:
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"),
])
Out[6]:

3. Horizontal Sticks

In [7]:
ggplot(data, aes('y', 'x')) + geom_lollipop(dir="h")
Out[7]:

4. Sloped Baseline

In [8]:
slope=0.5
intercept=1

abline=( 
    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 + geom_lollipop(intercept=intercept, slope=slope, shape=21) + ggtitle("dir='v' (default)"),
    abline + geom_lollipop(intercept=intercept, slope=slope, shape=21, dir="h") + ggtitle("dir='h'"),
    abline + geom_lollipop(intercept=intercept, slope=slope, shape=21, dir="s") + ggtitle("dir='s'"),
])
Out[8]:

5. Parameter stat

In [9]:
df = pd.read_csv("https://raw.githubusercontent.com/JetBrains/lets-plot-docs/master/data/mpg.csv")
df.head(3)
Out[9]:
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
In [10]:
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'"),
])
Out[10]:

6. Lollipops in Marginal Layer

In [11]:
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))
Out[11]:

7. Lollipops and a Regression Line

In [12]:
model = LinearRegression().fit(df[["hwy"]], df["cty"])
slope, intercept = model.coef_[0], model.intercept_

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