-1

I can't seem to get a legend to appear on this plot. Forums and web tutorials have not provided a solution. Any help would be appreciated.

I have created a bar plot that overlays frequencies when NA values are included and excluded but I need to provide a legend for the plot.

Full_Freq<-data.frame(NA_INC = c(11.8, 10.1, 11.9, 18.8, 17.8, 1.7, 1.7, 1.8, 3.5, .001),
                      NA_EXC = c(54.9, 38.6, 27.9, 34.7, 36.1, 2.3, 2.3, 2.8, 8.4, 100.0),
                      code = c("RI1 - R1,C1,A,G,R", "RI2 - R1,C1,A,E,R", "RC1 - R1,C1,A,E,R",
                               "RP3 - R2,C2,B1L1,BGLG,BRLR", "RP4 - R1,C1,A,P,O", "RM1 A - R3,C3,M1D1L1,MWDELE,MRDRLR",
                               "RM1 B - R3,C4,M2D1L1,MWDPLP,MRDRLO","RM2 - R3,C3,M1D1L1,MWDGLG,MRDRLR",
                               "RM3 - R3,C3,M1D1L1,MWDGLG,MRDRLR","RM4 - R1,C1,A,P,R"))

ggplot(Full_Freq) + 
  geom_col(aes(x = code, y = NA_EXC), fill = "gray",  colour = "black") + 
  geom_col(aes(x = code, y = NA_INC), fill = "black",  colour = "black")+
  ylab("Percentage")+
  xlab("")+
  ggtitle("Tooth and Full Phenotype Code")+
  theme_classic()+
  theme(plot.title = element_text(hjust= 0.5))+
  theme(axis.text.x = element_text(angle = 90, vjust=0.5))
dalek_fred
  • 153
  • 10
  • 1
    You need to reshape your data from wide to long. Gather columns `NA_INC` and `NA_EXC` then map the resulting value column to `y` and the resulting `key` column to the `fill` aesthetic. Both inside `aes()`. Related: [R - ggplot line color (using geom_line) doesn't change](https://stackoverflow.com/questions/48051905/r-ggplot-line-color-using-geom-line-doesnt-change) – markus Apr 07 '19 at 11:01
  • have the answers you have gotten been helpful? If any solved your problem consider accepting one as the answer. – Kresten May 21 '19 at 07:24

4 Answers4

1

First transform your data in a tidy way (one observation per row):

library(tidyverse)
Full_Freq <- Full_Freq %>%
  gather(key = IncExc, value = x, -code)

Then plot,

ggplot(Full_Freq) + 
  geom_col(aes(x = code, y = x, fill = IncExc)) + 
  ylab("Percentage")+
  xlab("")+
  ggtitle("Tooth and Full Phenotype Code")+
  theme_classic()+
  theme(plot.title = element_text(hjust= 0.5))+
  theme(axis.text.x = element_text(angle = 90, vjust=0.5)) + 
  theme(legend.position = "right")

You might need to change the colors.

Evert
  • 51
  • 4
  • Please include all packages that you're using – pogibas Apr 07 '19 at 11:07
  • Why 3 calls to theme? You can put everything in the same call. – Rui Barradas Apr 07 '19 at 11:16
  • Thank you for your help. While this does create a legend, it alters the data and doesn't present it accurately. For instance, when RI1 has NA values included, the bar is at 11.8%, and when excluded it is at 54.9%. However, after using reshape the values add together to equal 66.7% – dalek_fred Apr 07 '19 at 18:19
0

In many cases, making plots is easier with long data format. You can transform your data into long format with reshape2 (or also with tidyverse, as suggested in another answer):

library(reshape2)
# your code here

# reshaping your data into long format
Full_Freq.m <- melt(Full_Freq,id.vars = "code") 
Full_Freq.m
#                                 code variable   value
#1                   RI1 - R1,C1,A,G,R   NA_INC  11.800
#2                   RI2 - R1,C1,A,E,R   NA_INC  10.100
#3                   RC1 - R1,C1,A,E,R   NA_INC  11.900
#...
# 11                  RI1 - R1,C1,A,G,R   NA_EXC  54.900
# 12                  RI2 - R1,C1,A,E,R   NA_EXC  38.600
# 13                  RC1 - R1,C1,A,E,R   NA_EXC  27.900
# 14         RP3 - R2,C2,B1L1,BGLG,BRLR   NA_EXC  34.700
#...

Then making plots is easier. Plot with stacked bars:

# Making the plot
ggplot(data=Full_Freq.m, aes(x=code, y=value, fill=variable)) + geom_bar(stat="identity")+ 
  ylab("Percentage")+
  xlab("") +
  ggtitle("Tooth and Full Phenotype Code") +
  theme_classic() +
  theme(plot.title = element_text(hjust= 0.5))+
  theme(axis.text.x = element_text(angle = 90, vjust=0.5)) +   
  scale_fill_manual(values=c("grey", "black")) 

enter image description here

Plot with dodged bars:

# dodged bar plot, e.g. bars next to each other
ggplot(data=Full_Freq.m, aes(x=code, y=value, fill=variable)) + geom_bar(stat="identity", position="dodge")+ 
  ylab("Percentage")+
  xlab("") +
  ggtitle("Tooth and Full Phenotype Code") +
  theme_classic() +
  theme(plot.title = element_text(hjust= 0.5))+
  theme(axis.text.x = element_text(angle = 90, vjust=0.5)) +   
  scale_fill_manual(values=c("grey", "black")) 

enter image description here

Plot with overlaid bars:

# bars overlaid
ggplot(data=Full_Freq.m, aes(x=code, y=value, fill=variable)) + geom_bar(stat="identity", position="identity")+ 
  ylab("Percentage")+
  xlab("") +
  ggtitle("Tooth and Full Phenotype Code") +
  theme_classic() +
  theme(plot.title = element_text(hjust= 0.5))+
  theme(axis.text.x = element_text(angle = 90, vjust=0.5)) +   
  scale_fill_manual(values=c('NA_EXC' = 'gray', 'NA_INC' = 'black')) +
  geom_col(data=Full_Freq.m[which(Full_Freq.m$variable=="NA_INC"),])  

enter image description here

Oka
  • 1,318
  • 6
  • 11
  • Thank you for your help. While this does create a legend, it alters the data and doesn't present it accurately. For instance, when RI1 has NA values included, the bar is at 11.8%, and when excluded it is at 54.9%. However, after using reshape the values add together to equal 66.7% – dalek_fred Apr 07 '19 at 18:19
  • And how much you think 54.9+11.8 should be? 66.7% sound about correct.. – Oka Apr 07 '19 at 18:32
  • You're correct but that's not how I'm trying to visualize the data. I want the bars to overlay one another, not be stacked on top of another. – dalek_fred Apr 07 '19 at 20:23
  • Ok, so you wanted a bar plot that stacks frequencies, but which is not the stacked bar plot. Now it makes sense. – Oka Apr 07 '19 at 20:30
  • Yeah, I probably worded my question poorly. I did post a solution to my question though. – dalek_fred Apr 07 '19 at 21:02
  • @Oka if you want bars to be placed next to each other then put the argument `position = "dodge"`in the `geom_bar()` layer – Kresten Apr 08 '19 at 10:22
  • @JG1981: NP. I added that option to my answer now so it covers both, the question, and what you actually needed. – Oka Apr 08 '19 at 11:20
0

Thank you to everyone that helped. I've got my code sorted out minus having the variables on the x-axis in order. Here's how I did it -

````
### Barplot of full phenotype codes that have contrast frequencies when NA values are included/excluded 
Full_Freq<-data.frame(NA_INC = c(11.8, 10.1, 11.9, 18.8, 17.8, 1.7, 1.7, 1.8, 3.5, 0.001),
                      NA_EXC = c(54.9, 38.6, 27.9, 34.7, 36.1, 2.3, 2.3, 2.8, 8.4, 100.0),
                      code = c("RI1 - R1,C1,A,G,R", "RI2 - R1,C1,A,E,R", "RC1 - R1,C1,A,E,R",
                               "RP3 - R2,C2,B1L1,BGLG,BRLR", "RP4 - R1,C1,A,P,O", "RM1 A - R3,C3,M1D1L1,MWDELE,MRDRLR",
                               "RM1 B - R3,C4,M2D1L1,MWDPLP,MRDRLO","RM2 - R3,C3,M1D1L1,MWDGLG,MRDRLR",
                               "RM3 - R3,C3,M1D1L1,MWDGLG,MRDRLR","RM4 - R1,C1,A,P,R"))


#### make the plot
ggplot(Full_Freq) + 
  geom_col(aes(x = code, y = NA_EXC, fill = "NA excluded")) + 
  geom_col(aes(x = code, y = NA_INC, fill= "NA included")) +
  scale_fill_manual(name = 'NA Values', values = c('NA excluded' = 'gray', 'NA included' = 'black')) +
  ylab("Percentage")+
  xlab("")+
  ggtitle("Full Phenotype Code for Maxillary Teeth")+
  theme_classic()+
  theme(plot.title = element_text(hjust= 0.5))+
  theme(axis.text.x = element_text(angle = 90, hjust = 1, vjust=0.5))
````
dalek_fred
  • 153
  • 10
0

Adding to @Oka solution:

  1. tidy your data. I use tidyr::gather()
  2. plot dodged bar plot
    • reorder the x axis using reorder()
  3. fix theme, add lables

code

Full_Freq %>% 
tidyr::gather("variable", "value", contains("NA")) %>% 
ggplot(aes(x=reorder(code, value, max), y=value, fill=variable)) + geom_bar(stat="identity", position="dodge")+ 
  labs(fill = "legend title",
       x= "x title",
       y = "Percentage",
       title = "Tooth and Full Phenotype Code")+
  theme_classic() +
  theme(axis.text.x = element_text(angle = 90, vjust=0.5)) +   
  scale_fill_manual(values=c("grey", "black"))

enter image description here

Kresten
  • 1,758
  • 12
  • 18