Home > Blockchain >  In ggplot, segregate bar graphs based on value of another column
In ggplot, segregate bar graphs based on value of another column

Time:04-01

Using the following data frame:

dat <- structure(list(Model = c("I.E.T", "I.E.T.S", "I.E.T.N", "I.E.T.S.N", 
                                "F.D.E.T", "F.D.E.T.N", "F.D.E.T.S.N", "I.E.T", "I.E.T.S", "I.E.T.N", 
                                "I.E.T.S.N", "F.D.E.T", "F.D.E.T.N", "F.D.E.T.S.N", "I.E.T", 
                                "I.E.T.S", "I.E.T.N", "I.E.T.S.N", "F.D.E.T", "F.D.E.T.N", "F.D.E.T.S.N"), 
                      Errors = c("NO", "NO", "NO", "YES", "NO", "NO", "YES", "NO", 
                                 "NO", "NO", "NO", "NO", "NO", "NO", "NO", "NO", "NO", "YES", 
                                 "NO", "NO", "YES"),                     
                      Type = c("CF", "CF", "CF", "CF", "CF", "CF", 
                                 "CF", "BF", "BF", "BF", "BF", "BF", "BF", "BF", "MBF", "MBF", 
                                 "MBF", "MBF", "MBF", "MBF", "MBF"), 
                      Mean_Loadings = c(0.534, 0.591, 0.554, 0.581, 0.552, 0.569, 0.596, 0.196, 0.39, 0.306, 
                                       0.411, 0.174, 0.343, 0.429, 0.185, 0.248, 0.271, 0.292, 0.21, 
                                       0.343, 0.429)), 
                      class = "data.frame", row.names = c(NA, -21L))

I have created this plot:

dat$Model <- factor(dat$Model)
dat$Errors <- factor(dat$Errors, levels = c("NO", "YES"))
dat$Type <- factor(dat$Type, levels = c("CF", "MBF", "BF"))

ggplot(dat, aes(x = interaction(Model, Errors), y = Mean_Loadings, color = Type, fill = Type))   
  geom_rect(data=NULL, aes(xmin=7.5, xmax=Inf, ymin=-Inf, ymax=Inf), fill="#F9EBEA", color = "gray") 
  geom_bar(position = position_dodge2(width = 0.9, preserve = "single")
           , stat="identity") 
  scale_x_discrete(limits = NULL)  
  theme_bw()   
  labs(title = "",
       y = "Mean Loading",
       x = "Models",
       color = "Model Type",
       fill = "Model Type")  
  theme(panel.grid.major = element_blank(), panel.grid.minor = element_blank(),
        panel.background = element_blank(), axis.title=element_text(size=15),
        text = element_text(size = 14), plot.margin = margin(20, 50, 10, 20),
        axis.text.x=element_text(angle = -25, hjust = 0, size = 10), 
        axis.text.y=element_text(size = 20), axis.text=element_text(size=20))  
  theme(legend.position = "top")

How can the following be done?

  1. Remove ".NO" and ".YES" from the names of the models that show on the X-Axis. Or is there a better way of doing this whole plot besides x = interaction(Model, Errors)? The end goal is to segregate on the right models that produced errors (as indicated in the Errors column).
  2. Add some text to the top center of the red box on the right. e.g. "With Errors"
  3. Add a text box to the right of the plot.

CodePudding user response:

First, for removing the no and yes, you could create a simple function to extract the portions that you want for the labels. So, in interaction, I added _ as the separator, then we can just extract the portion proceeding that, which is added in scale_x_discrete as labels = make_labels. Second, for adding text to the red area, you can just use annotate. Third, for outside the area, we can again use annotate, but we want to add an additional line to allow plotting outside using coord_cartesian.

library(tidyverse)

make_labels <- function(labels) {
  result <- str_split(labels, "_")
  unlist(lapply(result, function(x) x[1]))
}


ggplot(dat, aes(x = interaction(Model, Errors, sep = "_"), y = Mean_Loadings, color = Type, fill = Type))   
  geom_rect(data=NULL, aes(xmin=7.5, xmax=Inf, ymin=-Inf, ymax=Inf), fill="#F9EBEA", color = "gray") 
  geom_bar(position = position_dodge2(width = 0.9, preserve = "single")
           , stat="identity") 
  scale_x_discrete(labels = make_labels, limits = NULL)  
  theme_bw()   
  labs(title = "",
       y = "Mean Loading",
       x = "Models",
       color = "Model Type",
       fill = "Model Type")  
  theme(panel.grid.major = element_blank(), panel.grid.minor = element_blank(),
        panel.background = element_blank(), axis.title=element_text(size=15),
        text = element_text(size = 14), plot.margin = margin(20, 80, 10, 20),
        axis.text.x=element_text(angle = -25, hjust = 0, size = 10), 
        axis.text.y=element_text(size = 20), axis.text=element_text(size=20))  
  theme(legend.position = "top")  
  annotate("text", x=8.5, y=0.65, label= "With Errors",
           family = "", fontface = 2, size=4)   
  annotate("text", x = 10, y = 0.65, label = "text",
           family = "", fontface = 2, size=4)  
  coord_cartesian(ylim = c(0, 0.7), xlim = c(0, 9), clip = "off")

Output

enter image description here

  • Related