0

I am trying to plot a bar chart where generic names of each group could be changed as desired by the user and plotted with a specific color in the defined order. I tried the following code but could not plot the chart as expected (i.e., veh = black, trtA = red, trtA = blue, trtAB = purple).

I need help with figuring out what am I missing? I checked the various posts a, b, c, d, etc., in this forum but, could not fix the issue.

  library(ggplot2)      
  
  GroupA <- "Vehicle"
  GroupB <- "Treatment-A"
  GroupC <- "Treatment-B"
  GroupD <- "Treatment-AB"

  z <- data.frame(group = c("trtA", "trtAB",  "trtB", "veh"),
                  Mean = c(42.990, 50.955, 34.235, 31.992),
                  sd = c(15.541, 18.325, 9.737, 12.463))

  z$group[z$group == "veh"] <- GroupA
  z$group[z$group == "trtA"] <- GroupB
  z$group[z$group == "trtB"] <- GroupC
  z$group[z$group == "trtAB"] <- GroupD
  
  # group - color mapping
  # veh = black, trtA = red, trtB = blue, trtAB = purple

  colorVals = c("black", "red", "blue", "purple")
  
  ggplot(z, aes(x=group, y=Mean, fill = group )) + 
      geom_bar(stat="identity", position=position_dodge()) +
      geom_errorbar(aes(ymin=Mean-sd, ymax=Mean+sd), width=.4) + 
      geom_text(aes(label=round(Mean,2), fontface = "bold"), vjust = -0.5) +
      labs(x = "Treatment Group", y = "Signal Value") +
      theme_classic(base_size = 14) +
      theme(legend.position='none')  + 
      theme(axis.text.x = element_text(angle = 20, hjust = 1)) +
      scale_fill_manual("legend", values = colorVals)
RanonKahn
  • 853
  • 10
  • 34

3 Answers3

1

Create a named vector :

library(ggplot2)

colorVals <- c('Vehicle' = 'Black', 'Treatment-A' = 'red', 
               'Treatment-B' = 'blue', 'Treatment-AB' = 'purple')

ggplot(z, aes(x=group, y=Mean, fill = group )) + 
  geom_bar(stat="identity", position=position_dodge()) +
  geom_errorbar(aes(ymin=Mean-sd, ymax=Mean+sd), width=.4) + 
  geom_text(aes(label=round(Mean,2), fontface = "bold"), vjust = -0.5) +
  labs(x = "Treatment Group", y = "Signal Value") +
  theme_classic(base_size = 14) +
  theme(legend.position='none')  + 
  theme(axis.text.x = element_text(angle = 20, hjust = 1)) +
  scale_fill_manual("legend", values = colorVals)

enter image description here

Ronak Shah
  • 377,200
  • 20
  • 156
  • 213
  • Appreciate the suggestion. However, the challenge is group names as mentioned in the question will be changing with the user and the experiment, and hence cannot be hardcoded. – RanonKahn Mar 18 '21 at 08:30
  • You can assign the group names as a vector to the `names()` of the colour vector, instead of specifying them one by one. – cymon Mar 18 '21 at 08:32
  • @RanonKahn If you don't know what the values are going to be then how do you know their corresponding colors? Are the colors fixed? Meaning the first value in the data is going to be black, second red and so on? – Ronak Shah Mar 18 '21 at 08:41
  • @RonakShah, Good question. This is part of a large RShiny app where the user would have an option to rename groups from 4 dedicated inputs for renaming each of the existing generic group names (veh, trtA, trtB, trtAB) from their experiment. Usually, the new names are longer describing each treatment. – RanonKahn Mar 18 '21 at 14:38
1

I've modified your question code to assign colour and new name and display them in requested order:

library(ggplot2)      

GroupA <- "Vehicle"
GroupB <- "Treatment-A"
GroupC <- "Treatment-B"
GroupD <- "Treatment-AB"

# Assign colour names without being explicit about the name values.
colorVals = c("black", "red", "blue", "purple")
names(colorVals) <- c(GroupA, GroupB, GroupC, GroupD)

# Need to do the same for the labels so the new names can be ordered by the old names
xvalues <- c("veh", "trtA", "trtB", "trtAB")   # just once each, in desired order.
names(xvalues) <- c(GroupA, GroupB, GroupC, GroupD)



z <- data.frame(group = c("trtA", "trtAB",  "trtB", "veh"),
                Mean = c(42.990, 50.955, 34.235, 31.992),
                sd = c(15.541, 18.325, 9.737, 12.463))

# Assign to a new variable to avoid NA from assigning values that are not included in the factor group.
z$label <- xvalues[z$group]

# Set as ordered factor to fix x axis order
z$label <- factor(z$label, ordered=TRUE, levels=names(xvalues))

ggplot(z, aes(x=label, y=Mean, fill = label )) + 
    geom_bar(stat="identity", position=position_dodge()) +
    geom_errorbar(aes(ymin=Mean-sd, ymax=Mean+sd), width=.4) + 
    geom_text(aes(label=round(Mean,2), fontface = "bold"), vjust = -0.5) +
    scale_fill_manual(values=colorVals) +
    labs(x = "Treatment Group", y = "Signal Value") +
    theme_classic(base_size = 14) +
    theme(legend.position='none')  + 
    theme(axis.text.x = element_text(angle = 20, hjust = 1)) +
    scale_fill_manual("legend", values = colorVals)
cymon
  • 413
  • 2
  • 9
  • I got the clues from your answer on what I was missing. I am posting my modified code inspired by your answer. – RanonKahn Mar 18 '21 at 15:20
0

I figured out the issues and have posted my answer inspired by @cymon's and @Ronak Shah's solutions.

library(ggplot2)

z <- data.frame(group = c("trtA", "trtAB",  "trtB", "veh"),
                Mean = c(42.990, 50.955, 34.235, 31.992),
                sd = c(15.541, 18.325, 9.737, 12.463))

colorVals = c("black", "red", "blue", "purple")

# Before assigning new values to existing 'group' values

ggplot(z, aes(x=group, y=Mean, fill = group )) + 
    geom_bar(stat="identity", position=position_dodge()) +
    geom_errorbar(aes(ymin=Mean-sd, ymax=Mean+sd), width=.4) + 
    geom_text(aes(label=round(Mean,2), fontface = "bold"), vjust = -0.5) +
    scale_fill_manual(values=colorVals) +
    labs(x = "Treatment Group", y = "Signal Value") +
    theme_classic(base_size = 14) +
    theme(legend.position='none')  + 
    theme(axis.text.x = element_text(angle = 20, hjust = 1)) +
    scale_fill_manual("legend", values = colorVals)

# After assigning new values to existing 'group' values

GroupA <- "Vehicle"
GroupB <- "Treatment-A"
GroupC <- "Treatment-B"
GroupD <- "Treatment-AB"

names(colorVals) <- c(GroupA, GroupB, GroupC, GroupD)

z$group[z$group == "veh"] <- GroupA
z$group[z$group == "trtA"] <- GroupB
z$group[z$group == "trtB"] <- GroupC
z$group[z$group == "trtAB"] <- GroupD

z$group <- factor(z$group, ordered=TRUE, levels=names(colorVals))

ggplot(z, aes(x=group, y=Mean, fill = group )) + 
    geom_bar(stat="identity", position=position_dodge()) +
    geom_errorbar(aes(ymin=Mean-sd, ymax=Mean+sd), width=.4) + 
    geom_text(aes(label=round(Mean,2), fontface = "bold"), vjust = -0.5) +
    scale_fill_manual(values=colorVals) +
    labs(x = "Treatment Group", y = "Signal Value") +
    theme_classic(base_size = 14) +
    theme(legend.position='none')  + 
    theme(axis.text.x = element_text(angle = 20, hjust = 1)) +
    scale_fill_manual("legend", values = colorVals)
RanonKahn
  • 853
  • 10
  • 34