user3542212
user3542212

Reputation: 111

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

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.

Upvotes: 0

Views: 70

Answers (1)

AndrewGB
AndrewGB

Reputation: 16866

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

Upvotes: 4

Related Questions