Search code examples
rggplot2geom-bargeom-point

geom_bar grouped data with geom_point color based on values


I would like to add geom_point showing value of sect to my grouped geom_bar showing value of perc with point colour based on conditional data

My data is like this:

```structure(list(year = c(2019, 2019, 2019, 2018, 2018, 2018, 2017, 
2017, 2017, 2020, 2020, 2020), ques = c("q1", "q2", "q3", "q1", 
"q2", "q3", "q1", "q2", "q3", "q1", "q2", "q3"), sect = c(94.25, 
99, 86.33, 94.19, 92.21, 90.42, 98.88, 89.31, 82.76, 82.06, 75.46, 
59.39), perc = c(88.79, 94.71, 89.46, 89.69, 81.29, 84.1, 90.18, 
89.1, 73.38, 70.66, 97, 75.99), diff = c(-5.46, -4.29, 3.13, 
-4.5, -10.92, -6.32, -8.7, -0.21, -9.38, -11.4, 21.54, 16.6), 
    ci = c(12.76572759, 12.76572759, 12.76572759, 12.76572759, 
    12.76572759, 12.76572759, 12.76572759, 12.76572759, 12.76572759, 
    12.76572759, 12.76572759, 12.76572759)), class = c("spec_tbl_df", 
"tbl_df", "tbl", "data.frame"), row.names = c(NA, -12L), spec = structure(list(
    cols = list(year = structure(list(), class = c("collector_double", 
    "collector")), ques = structure(list(), class = c("collector_character", 
    "collector")), sect = structure(list(), class = c("collector_double", 
    "collector")), perc = structure(list(), class = c("collector_double", 
    "collector")), diff = structure(list(), class = c("collector_double", 
    "collector")), ci = structure(list(), class = c("collector_double", 
    "collector"))), default = structure(list(), class = c("collector_guess", 
    "collector")), skip = 1), class = "col_spec"))

The table is like this:

```    year ques   sect  perc   diff    ci
   <dbl> <chr> <dbl> <dbl>  <dbl> <dbl>
 1  2019 q1     94.2  88.8  -5.46  12.8
 2  2019 q2     99    94.7  -4.29  12.8
 3  2019 q3     86.3  89.5   3.13  12.8
 4  2018 q1     94.2  89.7  -4.5   12.8
 5  2018 q2     92.2  81.3 -10.9   12.8
 6  2018 q3     90.4  84.1  -6.32  12.8
 7  2017 q1     98.9  90.2  -8.7   12.8
 8  2017 q2     89.3  89.1  -0.21  12.8
 9  2017 q3     82.8  73.4  -9.38  12.8
10  2020 q1     82.1  70.7 -11.4   12.8
11  2020 q2     75.5  97    21.5   12.8
12  2020 q3     59.4  76.0  16.6   12.8

The simple code:

```df %>% 
  ggplot(aes(fill=ques, y = perc, x = year)) +
  geom_bar(position="dodge", stat="identity")+
  geom_point()

The colour conditions I would like for the points are:

```df <- df %>%
  mutate(
    color = case_when(
      diff >= ci ~ "green",
      diff <= -ci ~ "red",
      TRUE ~ "grey"
    )
  )

As a first step I can't get the dots to appear over relevant bars: this shows points vertically but I would like them horizontal over relevant years So I would be grateful for help showing points over relevant years, and also incorporating the colour conditions to show green for diff >= ci, red <= - ci, and grey for neither. Hope this makes sense and thanks


Solution

  • You can use position_dodge in the geom_point call to match the points to the bars. To get the colours right you map the new column color to the colour scale and add a call to scale_color_identity.

    If I understand your logic correctly, none of the points in your data frame will end up red, since none of the values of diff are less than -12.8

    df %>%   
      mutate(color = case_when(diff >= ci ~ "green",
                               diff <= -ci ~ "red",
                               TRUE ~ "gray20")) %>%
      ggplot(aes(fill=ques, y = perc, x = year)) +
      geom_bar(position="dodge", stat="identity")+
      geom_point(aes(color = color), 
                 position = position_dodge(width = 0.9), size = 3) +
      scale_color_identity()
    

    enter image description here