making paired points in ggplot for multiple categories

Viewed 370

I know this question has been answered before however, its not doing what I want it to do. I have a dataframe in R. And I want to make paired points between different categories. The dataframe is:


sample <- data.frame(city_name = c(rep('Wahsington',10),rep('Seattle',10)),
                     experience = rep(c("ten","five"),5),
                     test = rep(c('manager','manager','team lead','team lead',
                                  'CFO','CFO','CEO','CEO','Executive',
                                  'Executive'),2),
                     score = c(87.10,27.20,98.15,67.20,68.30,23.00,78.75,49.30,63.30,37.90,
                                    69.10,20.20,90.65,56.05,69.40,47.35,52.55,37.85,
                                    70.90,47.75))

And in order to draw paired points I do:


options(repr.plot.width=30, repr.plot.height=8)
ggplot(sample, aes(x = test, y = score, group = test)) + 
geom_line() + 
geom_point(size = 2, aes(color = experience)) + 
facet_wrap(~ city_name) +
scale_x_discrete("") +
theme_minimal() +
  ylab('Score') + xlab('') + theme(axis.text.x=element_text(angle = 90, hjust = 0))

The plot I get looks like:

ggplot for my dataframe

However, I these paired point not to fall below one another but rather be a little tilted for aesthetics purposes as here but for different categories like 'CFO' and 'CEO' annotated on x-axis like in the first graph:

enter image description here

How can I achieve that using ggplot in R?

Edit: This is an example of what I want to achieve:

enter image description here

2 Answers

One way to do this is to make the x axis continuous for experience and test values; an x offset is used where experience is "ten".

library(ggplot2)
library(dplyr)

offset = 0.4

# modify the data to allow for x values to control the location of points and line ends.

df <- 
  df %>% 
  group_by(city_name, experience) %>% 
  arrange(city_name, experience, test) %>% 
  mutate(x = as.numeric(row_number()),
         x_lab_pos = x + 0.5 * offset, 
         x = if_else(experience == "ten", x + offset, x))

x_breaks <- sort(unique(df$x_lab_pos))
x_label <- sort(unique(df$test))

ggplot(df, aes(x = x, y = score, group = test)) + 
  geom_line() + 
  geom_point(size = 2, aes(color = experience)) +
  facet_wrap(~ city_name) +
  scale_x_continuous(breaks = x_breaks,
                     labels = x_label) +
  theme_minimal() +
  labs(x = NULL,
       y = 'Score') +
  theme(axis.text.x=element_text(angle = 90, hjust = 0))

Created on 2021-12-12 by the reprex package (v2.0.1)

data

df <- data.frame(city_name = c(rep('Washington',10),rep('Seattle',10)),
                     experience = rep(c("ten","five"),5),
                     test = rep(c('manager','manager','team lead','team lead',
                                  'CFO','CFO','CEO','CEO','Executive',
                                  'Executive'),2),
                     score = c(87.10,27.20,98.15,67.20,68.30,23.00,78.75,49.30,63.30,37.90,
                               69.10,20.20,90.65,56.05,69.40,47.35,52.55,37.85,
                               70.90,47.75))

Another option is to use nested faceting (using {ggh4x}). (It doesn't really give your desired look, but just pointing out that option). See also further below for a suggestion of a different way to visualise your paired data - with a scatter plot.

library(tidyverse)
library(ggh4x)
## bad idea to call an object like a very commonly used function (sample)
## df is also a function, but much less commonly used
df <- data.frame(city_name = c(rep('Wahsington',10),rep('Seattle',10)),
                     experience = rep(c("ten","five"),5),
                     test = rep(c('manager','manager','team lead','team lead',
                                  'CFO','CFO','CEO','CEO','Executive',
                                  'Executive'),2),
                     score = c(87.10,27.20,98.15,67.20,68.30,23.00,78.75,49.30,63.30,37.90,
                               69.10,20.20,90.65,56.05,69.40,47.35,52.55,37.85,
                               70.90,47.75))
ggplot(df, aes(x = experience, y = score, group = test)) + 
  geom_line() + 
  geom_point(size = 2, aes(color = experience)) + 
  facet_nested(~ city_name + test) +
  ## one call to labs reduces the code to relabel the axis
  labs(x = NULL, y = "Score") + 
  theme_minimal() +
  theme(axis.text.x=element_blank())

paired data can be more compellingly visualised with a scatter plot

df_wide <- 
  df %>% 
  pivot_wider(names_from = experience, values_from = score)

lims <- c(0, 100)

ggplot(df_wide, aes(five, ten, color = test)) +
  geom_point() +
  geom_abline(slope = 1, intercept = 0) +
  ggrepel::geom_text_repel(aes(label = test)) +
  scale_color_brewer(NULL, palette = "Set1") +
  facet_grid(~city_name) +
  coord_equal(xlim = lims, ylim = lims) +
  cowplot::theme_minimal_grid() +
  theme(legend.position = "none")

Created on 2021-12-12 by the reprex package (v2.0.1)

Related