Search code examples
rggplot2plotlygeom-barggplotly

Issue with "na" in arranging the bars in a bar plot in R and ggplot2


I am trying to create a Descending bars bar plot using ggplot2 and plotly in R. The data I am using is "a12" which is consumed by the ggplot under the line "#Final Data frame is consumed below".

If you see the snap shot below, the "na" value in the column "a1" should come at second spot in the plot, however it does not follow the descending order and is pushed at the last.

One way to cure this issue is to hardcode the value there, but I don't want to do that. Instead is there a way using which I can make "na" follow the order without hard coding any value?

Note: Please do not modify the data above the line "#Final Data frame is consumed below". The actual data I am working on is actually in the same format. Please help.

a1 = c("A","","B","C","D","F")
b1 = c(165,154,134,110,94,78)
a12 = data.frame(a1,b1)
a12[2, 1] = "NA"

#Final Data frame is consumed below
pp1 <<- ggplot(a12 , 
               aes(x = reorder(a1, -b1), 
                   y = b1,
                   text = paste("User: <br>", a1, "<br> Days: <br>", round(b1)))) + 
  geom_bar(stat = "identity", fill = "#3399ff" ) + 
  scale_y_continuous(name = "Time") + 
  scale_x_discrete(name = "Employee") 

ggplotly(pp1, tooltip="text", height = 392)

Addon Script below:

a1 = c("A",NA,"B","C","D","F")
b1 = c(165,154,134,110,94,78)
a12 = data.frame(a1,b1,stringsAsFactors = FALSE)
pp1 <<- ggplot(a12 , aes(x = reorder(a1,-b1), y = b1,text=paste("User: 
<br>",a1, "<br> Days: <br>", round(b1)))) + 
geom_bar(stat = "identity", fill = "#3399ff" ) + scale_y_continuous(name 
="Time") + scale_x_discrete(name ="Employee") 
ggplotly(pp1, tooltip="text",height = 392)

enter image description here


Solution

  • In order to arrange the bars in the way you want, there should not be a missing value, i.e. NA, in df$a1. We somehow need to replace that missing value.

    Since you asked for "no replacement, no modification to the data" in the comments above, I suggest you replace the missing values inside the call to ggplot using, e.g. tidyr::replace_na. This will leave your original data unchanged.

    library(tidyr)
    library(ggplot2)
    pp1 <- ggplot(data = replace_na(a12, replace = list(a1 = "NA")),
                          aes(x = reorder(a1, -b1),
                              y = b1,
                              text = paste("User: <br>", a1, "<br> Days: <br>", round(b1)))) +
      geom_bar(stat = "identity", fill = "#3399ff") +
      scale_y_continuous(name = "Time") +
      scale_x_discrete(name = "Employee")
    
    ggplotly(pp1, tooltip = "text",height = 392)
    

    enter image description here

    I hope this helps.