anpami
anpami

Reputation: 888

dodging dots with geom_dotplot() if number of dots exceeds n for an x value

This is my dataframe:

DF <- structure(list(pub_year = c(2022, 2023, 2022, 2022, 2021, 2023, 2019, 
                                  2022, 2022, 2022, 2022, 2023, 2019, 2020, 
                                  2020, 2021, 2021, 2019, 2021, 2023), 
                     mega = c(1, 1, 1, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 
                              0, 1, 1, 1, 1, 0, 1)), 
                 row.names = c(NA, -20L), 
                 class = c("tbl_df", "tbl", "data.frame"))

Creating a dotplot, I get something like this:

This is the code:

library(tidyverse)
library(ggExtra)

yHeight <- 10
binwidth <- 0.5
dotsize <- 0.5

DF %>%
  ggplot(aes(x = reorder(pub_year, -pub_year), fill = factor(mega))) +
  geom_dotplot(method = "histodot", dotsize = dotsize,
               binwidth = binwidth, stackgroups = T,
               binpositions = "all",
               stackdir = "up", stackratio = 1) +
  scale_fill_manual(values = c("#8FBEE5", "#DEE7EC"),
                    name = "TEST",
                    labels = c("≤ 40", "> 40")) +
  scale_y_continuous(limits=c(0, 1), expand = c(0, 0), breaks = seq(0, 1, 1/yHeight), labels = seq(0, yHeight)) +
  theme_minimal() +
  theme(axis.ticks = element_blank(),
        axis.title = element_blank(),
        #axis.text.y = element_blank(),
        axis.line = element_blank(),
        legend.position = "right",
        panel.grid.minor = element_blank()) +
  coord_fixed(ratio=binwidth*dotsize*yHeight) +
  ggExtra::removeGridX()

My question:

I want to have just 5 dots per value -- for example, there are 7 dots in the value "2022" now, but I want to have them dodged such that one "column" has 5 dots and another 2, something like below graph. How can I achieve that?

Upvotes: 1

Views: 43

Answers (1)

M--
M--

Reputation: 28826

library(tidyverse)
library(ggExtra)

#yHeight <- 10
binwidth <- 0.5
dotsize <- 0.5
max_dots <- 5

DF %>% 
  mutate(y = 1:n(), .by = pub_year,
         y = if_else(y > max_dots , y - max_dots, y) / 2) %>% 
  ggplot(aes(x = reorder(pub_year, -pub_year), y = y, fill = factor(mega))) +
  geom_dotplot(binaxis="y", 
               binwidth = binwidth, stackgroups = T,
               binpositions = "all",
               stackdir = "centerwhole", stackratio = 1)+
  scale_fill_manual(values = c("#8FBEE5", "#DEE7EC"),
                    name = "TEST",
                    labels = c("≤ 40", "> 40"))+
  scale_y_continuous(limits=c(0, max_dots / 2 + dotsize), expand = c(0, 0),
                     breaks = seq(dotsize, max_dots/2, dotsize), 
                     labels = seq(dotsize, max_dots/2, dotsize)) +
  theme_minimal() +
  theme(axis.ticks = element_blank(),
        axis.title = element_blank(),
        axis.text.y = element_blank(),
        axis.line = element_blank(),
        legend.position = "right",
        panel.grid.minor = element_blank()) +
  coord_fixed(ratio=binwidth*dotsize*max_dots/2) +
  ggExtra::removeGridX()

Created on 2023-11-16 with reprex v2.0.2

Upvotes: 1

Related Questions