'How to customize Horizontal dots plot?

I want to plot customized Horizontal dots using my data and the code given here data:

df <- data.frame (origin = c("A","B","C","D","E","F","G","H","I","J"),
              Percentage = c(23,16,32,71,3,60,15,21,44,60),
              rate = c(10,12,20,200,-25,12,13,90,-105,23),
              change = c(10,12,-5,12,6,8,0.5,-2,5,-2))

.

      origin Percentage rate change
1       A         23   10   10.0
2       B         16   12   12.0
3       C         32   20   -5.0
4       D         71  200   12.0
5       E          3  -25    6.0
6       F         60   12    8.0
7       G         15   13    0.5
8       H         21   90   -2.0
9       I         44 -105    5.0
10      J         60   23   -2.0

obs from 'origin' column need be put on y-axis. corresponding values in 'change' and 'rate' column must be presented/differentiated through in box instead of circles, for example values from 'change' column in lightblue and values from 'rate' column in blue. In addition I want to add second vertical axis on right and put circles on it which size will be defined based on corresponding value in 'Percentage' column.

Output of code from the link: enter image description here

Expected outcome (smth. like this: enter image description here



Solution 1:[1]

Try this.

First, reshaping so that both rate and change are in one column better supports ggplot's general preference towards "long" data.

df2 <- reshape2::melt(df, id.vars = c("origin", "Percentage"))

(That can also be done using pivot_wider.)

The plot:

ggplot(df2, aes(value, origin)) +
  geom_label(aes(label = value, fill = variable, color = variable)) +
  geom_point(aes(size = Percentage), x = max(df2$value) +
20, shape = 21) +
  scale_x_continuous(expand = expansion(add = c(15, 25))) +
  scale_fill_manual(values = c(change="lightblue", rate="blue")) +
  scale_color_manual(values = c(change="black", rate="white")) +
  theme_bw() +
  theme(panel.border = element_blank(), panel.grid.major.x = element_blank(), panel.grid.minor.x = element_blank()) +
  labs(x = NULL, y = NULL)

enter image description here

The legend and labels can be adjusted in the usual ggplot methods. Overlapping of labels is an issue with which you will need to contend.

Solution 2:[2]

Update on OP request: See comments:

gg_dot +
  geom_text(aes(x = rate, y = origin, 
                label = paste0(round(rate, 1), "%")),
            col = "black") +
  geom_text(aes(x = change, y = origin, 
                label = paste0(round(change, 1), "%")),
            col = "white") +
  geom_text(aes(x = x, y = y, label = label, col = label),
            data.frame(x = c(40 - 1.1, 180 + 0.6), y = 11, 
                       label = c("change", "rate")), size = 6) +
  scale_color_manual(values = c("#9DBEBB", "#468189"), guide = "none") +
  scale_y_discrete(expand = c(0.2, 0)) 

enter image description here

First answer: Something like this?

library(tidyverse)
library(dslabs)

gg_dot <- df %>% 
  arrange(rate) %>%
  mutate(origin = fct_inorder(origin)) %>% 
  ggplot() +
  # remove axes and superfluous grids
  theme_classic() +
  theme(axis.title = element_blank(),
        axis.ticks.y = element_blank(),
        axis.line = element_blank()) +
  # add a dummy point for scaling purposes
  geom_point(aes(x = 12, y = origin), 
             size = 0, col = "white") +
  
  # add the horizontal discipline lines
  geom_hline(yintercept = 1:10, col = "grey80") +
  
  # add a point for each male success rate
  geom_point(aes(x = rate, y = origin), 
             size = 11, col = "#9DBEBB") +
  # add a point for each female success rate
  geom_point(aes(x = change, y = origin),
             size = 11, col = "#468189") 



gg_dot +
  geom_text(aes(x = rate, y = origin, 
                label = paste0(round(rate, 1))),
            col = "black") +
  geom_text(aes(x = change, y = origin, 
                label = paste0(round(change, 1))),
            col = "white") +
  geom_text(aes(x = x, y = y, label = label, col = label),
            data.frame(x = c(40 - 1.1, 180 + 0.6), y = 11, 
                       label = c("change", "rate")), size = 6) +
  scale_color_manual(values = c("#9DBEBB", "#468189"), guide = "none") +
  scale_y_discrete(expand = c(0.2, 0)) 

enter image description here

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1
Solution 2