How to not have percentage labels overlap (repel percentage labels) in Likert bar plot?

1k views Asked by At

I'm still relatively new to R, so any help here is very appreciated.

I created a Likert bar plot, but some of the percentages shown on the plot overlap. I am wondering how to prevent this overlap from occurring? I read about ggrepel, and tried to incorporate ggrepel code but have been unsuccessful. Does anyone know if code exists to ask the percentages shown on the plot (i.e. from plot.percents=TRUE) to not overlap?

Here is my code without an attempt to incorporate ggrepel:

likert.bar.plot(likert_Prevention.ALL, plot.percents=TRUE, plot.percent.high= FALSE, plot.percent.low=FALSE, 
            center = 3, low.color = "grey72", high.color = "red3", neutral.color = "lightsalmon",
            legend.position = "bottom", text.size=3.5)

and my attempt to incorporate ggrepel:

likert.bar.plot(likert_Prevention.ALL, plot.percents=TRUE, plot.percent.high= FALSE, plot.percent.low=FALSE, 
            center = 3, low.color = "grey72", high.color = "red3", neutral.color = "lightsalmon",
            legend.position = "bottom", text.size=3.5) + labs(geom_label_repel()) + labs(geom_text_repel())

Below is a cropped image of the overlapping percentages currently:

Likert bar plot with overlapping percentages

Thank you in advance for your help and time! Please let me know if any clarification is needed, as this is my first post to stackoverflow.

1

There are 1 answers

0
StupidWolf On

Not the easiest thing to do and I don't know if the flying arrows make it more complicated. Here is something using an example data:

library(likert)
library(ggplot2)
library(plyr)
library(dplyr)
data(pisaitems)

items29 <- pisaitems[,substr(names(pisaitems), 1,5) == 'ST25Q']
names(items29) <- c("Magazines", "Comic books", "Fiction", 
                        "Non-fiction books", "Newspapers")
l29 <- likert(items29)

The default looks like this:

likert.bar.plot(l29, plot.percents=TRUE, plot.percent.high= TRUE, 
plot.percent.low=TRUE, center = 3, low.color = "grey72", high.color = "red3", 
neutral.color = "lightsalmon",legend.position = "bottom", text.size=3.5)

enter image description here

You make a plot without the labels:

p = likert.bar.plot(l29, plot.percent.neutral=FALSE, plot.percent.high= FALSE, 
plot.percent.low=FALSE, center = 3, low.color = "grey72", high.color = "red3", 
neutral.color = "lightsalmon",legend.position = "bottom", text.size=3.5)

Pull out the neg, positive and neutral coordinates:

dat_pos = g$data %>% filter(value>0) %>% 
group_by(Item) %>% arrange(variable) %>%
mutate(ycoord=cumsum(value)-0.5*value) %>%
slice(2:n())

dat_neg = g$data %>% filter(value<0) %>% 
group_by(Item) %>% arrange(desc(variable)) %>%
mutate(ycoord=cumsum(value)-0.5*value) %>%
mutate(value=abs(value)) %>% slice(2:n())

dat_neu = g$data %>% group_by(Item) %>% 
filter(duplicated(variable)) %>% 
mutate(value=2*abs(value),ycoord=0) 

And add that to the plot:

p + geom_label_repel(data=rbind(dat_neu,dat_pos,dat_neg),
aes(x=Item,y=ycoord,label=paste0(round(value),"%")),size=3,force=10)

enter image description here