How to create this visualisation?

I came across this graph in a BBC article showing how cases have changed in different parts of the UK over two weeks:

I just thought it looked cool and was wondering if anyone knows what this type of graph is called or how to make one? Any help would be appreciated :slight_smile:

Link to article: https://www.bbc.co.uk/news/health-53280238

1 Like

hey @56anna

It’s called a lollipop plot.

This link should help you. I haven’t tried this plot yet in Python though. Maybe we can try and share our codes!

link here - https://python-graph-gallery.com/184-lollipop-plot-with-2-groups/

3 Likes

Thank you very much! If I get a chance to use this kind of plot, I will share my code :slight_smile:

2 Likes

I love this type of plot, Anna, and recently used it in a project: Here’s the code I used.

def changeplot(names, before, after, metric='', title='', sortby='before'):    
# This is just data prep, specific to my dataset.
df = pd.DataFrame(np.array([before, after, names]).T, columns=['before','after','names'])
df = df.sort_values(sortby, ascending=True)
df['delta'] = np.abs(df.after - df.before)
df['lims'] = (df.before < df.after)
errs = np.array([df.apply(lambda x: 0 if x.lims else x.delta, axis=1), 
                 df.apply(lambda x: 0 if not x.lims else x.delta, axis=1)])

sns.set(style="white", context="talk")
fig, ax = plt.subplots(figsize=(8, 4))

# !!! This is where the magic happens - I use the errorbar type, but I format it as circles
ax.errorbar(df.before, df.names, xerr=errs, xlolims =df.lims, xuplims = ~df.lims, fmt='o')

# The rest is just some nice formatting, I added a label above each line with the change % etc.
ax.set(title=metric + title, ylabel = 'Ad Network', xlabel = metric)
newlim = ax.get_xlim()[1]+(ax.get_xlim()[0]/2.0)
ax.set_xlim((0, newlim))
ax.barh(df.names, np.repeat(newlim, len(df)), align='center', height=1.0, 
        color=(['lightgray', 'white']*len(df))[0:len(df)])
labels = ax.get_yticklabels()
plt.setp(labels, fontsize=14)
for i,(idx,t) in enumerate(df.iterrows()):
    ax.text(t.before - 0.5*errs[0][i] + 0.5*errs[1][i], t.names, 
            '{:+1.0f}%'.format(100.0*(t.after-t.before)/t.before), fontsize=12,
            color='darkgreen' if t.lims else 'darkred',
            verticalalignment="bottom", horizontalalignment="center")

plt.margins(0)
sns.despine(left=False, bottom=False, right=True)
return plt

changeplot(df.adnet, df.before, df.after, metric=’…’,
title=’ …’).show()

(BTW if anyone here needs some help I’m giving my time for free on educated-guess.com/contact )

3 Likes