Search code examples
rplotpositionlegend

Method for setting the legend outside a plot


All of the solutions that I've seen to this problem so far, involve manually setting the coordinates of the legend so that it's outside of the plot. I have >100 plots and so want to be able to reuse the same code on each of them to place the legend outside of the plot by default.

Here's two data frames, one with successful job applicants and one with everyone that applied for the position:

Id <- c(1,5,7,9,11,12,13,15,17,18)
Type <- c("Beginner", "Expert", "Intermediate", "Beginner", 
"Professional", "Expert", "Intermediate", "Professional", "Professional", 
"Expert")
Response<- c(0,1,2,2,1,2,1,2,1,1)
Successful <- data.frame(Id, Type, Response)
Successful

#   Successful
Id  Type             Response    
1   Beginner         0
5   Expert           1
7   Intermediate     2
9   Beginner         2
11  Professional     1
12  Expert           2
13  Intermediate     1
15  Professional     2
17  Professional     1
18  Expert           1

Id <- c(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18)
Type <- c("Beginner", "Expert", "Professional", "Beginner", "Expert", 
"Expert", "Intermediate", "Expert", "Beginner", "Intermediate", 
"Professional", "Expert", "Intermediate","Intermediate", "Professional", 
"Beginner", "Professional","Expert")
Response<- c(0,2,2,1,1,0,2,0,2,0,1,2,1,1,2,2,1,1)
AllApplicants <- data.frame(Id, Type, Response)
AllApplicants

#   AllApplicants
Id  Type             Response        
1   Beginner         0
2   Expert           2
3   Professional     2
4   Beginner         1
5   Expert           1
6   Expert           0
7   Intermediate     2
8   Expert           0
9   Beginner         2
10  Intermediate     0
11  Professional     1
12  Expert           2
13  Intermediate     1
14  Intermediate     1
15  Professional     2
16  Beginner         2
17  Professional     1
18  Expert           1

If we produce a plot of this data:

colors <- c("red", "orange", "green")
barplot(round(100*prop.table(table(AllApplicants$Response, 
AllApplicants$Type),2), 1),
    main="Responses of applicants", xlab="Level", ylab= "Proportion", 
    col=colors, legend.text = T)

The legend shows up overlapping the plot. I'm aware that it's possible to set the margins of the graph and the positioning of the legend manually:

par(mar=c(5.1,4.1,4.1,8))
legend(5,90, legend=c(0,1,2), fill=colors, xpd=T)

However, I'm hoping to keep the legend that's automatically generated if I include legend.text=TRUE in the barplot() function, and make it so that it automatically places the legend outside and to the right of the plot. I also need it to stay there when I resize the plot and zoom.

Any help would be greatly appreciated!


Solution

  • Would a ggplot2 solution work?

    library(ggplot2)
    
    df <- as.data.frame(round(100*prop.table(table(AllApplicants$Response, AllApplicants$Type),2), 1))
    
    ggplot(df, aes(x=Var2, y=Freq)) + 
    geom_col(aes(fill=Var1)) + 
    ggtitle("Responses of applicants") + 
    theme(plot.title = element_text(hjust=0.5)) + 
    xlab("Level") + ylab("Proportion") + 
    theme(legend.title = element_blank())
    

    pic