Recreating a Dumbbell Graph in R
How have moral attitudes changed in the past thirty years?
Ipsos MORI conducted two surveys, around 30 years apart, asking people what they believe is immoral. This article looks at how to recreate the dumbbell graph used in their article in R.
Between two surveys
In March 1989, the social research company Ipsos MORI asked 1,458 adults in face-to-face interviews:
Here is a list of issues some people might think are immoral or morally wrong. Which of them, if any, do you personally think are morally wrong?
Various items were listed. In partnership with the Policy Institute at King’s College London, Ipsos MORI conducted a second study in June to July 2019, talking to 1,021 adults (aged 15 or over). Their article showed a dumbbell graph created in Datawrapper:

Some items given in the graph are shortened from what was said to respondents, such as:
The use of hard drugs such as heroin
Changes in the survey structure — such as using different characteristics to “reflect the GB population profile” — are unlikely to explain these large differences between the two surveys.
Recreating the graph
In the ggalt package in R, there is the ‘geom_dumbbell’ tool. Additionally, we need to replicate the various labels. A similar article looked at recreating a graph produced by Pew Research Center.
The ‘tidy’ version of the data-set should remain in its tabular form, because the two observations (1989 and 2019) are needed separately (for ‘x’ and ‘xend’). A sign function is used later, to make the labels face the right way:
Ipsos_MORI_df <- Ipsos_MORI_df %>% mutate(Sgn = sign(y1989 - y2019 + 0.005))
The colours used are to match the Ipsos MORI report. The crux is the graph is the following code:
Ipsos_MORI_gg <- ggplot(Ipsos_MORI_df, aes(y=Issue, x=y1989, xend=y2019)) +
geom_dumbbell(size=3, color="#8AB0BD",
colour_x = "#EE7523",
colour_xend = "#6D3A5D",
dot_guide=FALSE) +
After that, we put the two labels representing the years, above the first line. The first label is given here:
geom_text(data=filter(Ipsos_MORI_df,
Issue=="Soft drugs (e.g. Cannabis)"),
aes(x=y1989, y=Issue, label="1989"),
color="#EE7523", size=5, vjust=-2,
fontface="bold", family="Calibri") +
Labelling the title, subtitle and caption comes next. We put labels for each year next to the issues, such as this label for 1989:
geom_text(data=Ipsos_MORI_df,
aes(x=y1989, y=Issue, label=percent_calc(y1989)),
color="#EE7523", size=3,
hjust=-Ipsos_MORI_df$Sgn*2, family="Calibri") +
The final graph then looks like:

More work could be done to exactly match the original graph, such as changing the font and text sizes from this ‘clean’ theme. This is a good visualisation, as a bar graph with 20 sets would be unwieldy look at.
The full code may be read at R Pubs, and the Excel data file is available to download from Google Sheets.