0

I am trying to plot the parameter estimates and levels of hierarchy from a stan model output. For the legend, I am hoping to remove all labels except for the "Overall Effects" label but I can't figure out how to remove all of the species successfully.

Here is the code:

ggplot(dfwide, aes(x=Estimate, y=var, color=factor(sp), size=factor(rndm),
                   alpha=factor(rndm))) + 
  geom_point(position =pd) + 
  geom_errorbarh(aes(xmin=(`2.5%`), xmax=(`95%`)), position=pd, 
                     size=.5, height = 0, width=0) + 
  geom_vline(xintercept=0) + 
  scale_colour_manual(values=c("blue", "red", "orangered1","orangered3", "sienna4",
                               "sienna2", "green4", "green3", "purple2", "magenta2"), 
                      labels=c("Overall Effects", expression(italic("A. pensylvanicum"), 
                               italic("A. rubrum"), italic("A. saccharum"), 
                               italic("B. alleghaniensis"), italic("B. papyrifera"), 
                               italic("F. grandifolia"), italic("I. mucronata"),
                               italic("P. grandidentata"), italic("Q. rubra")))) +
  scale_size_manual(values=c(3, 1, 1, 1, 1, 1, 1, 1, 1, 1)) + 
  scale_shape_manual(labels="", values=c("1"=16,"2"=16)) + 
  scale_alpha_manual(values=c(1, 0.4)) + guides(size=FALSE, alpha=FALSE) + 
  ggtitle(label = "A.") + 
  scale_y_discrete(limits = rev(unique(sort(dfwide$var))), labels=estimates) + 
  ylab("") + 
  labs(col="Effects") + theme(legend.title=element_blank())

enter image description here

neilfws
  • 32,751
  • 5
  • 50
  • 63

2 Answers2

2

The key points you need to notice is that remove part of the labels in legend can't be achieved by the function in ggplot2, what you need to do is interact with grid, which more underlying since both lattice and ggplot2 are based grid,to do some more underlying work, we need some functions in the grid.

To remove part of the labels in legend, there are three functions need to be used, they are grid.force(), grid.ls() and grid.remove() . After draw the picture by ggplot2, then using grid.force() and grid.ls(), we can find all the elements in the picture, they all are point, line, text, etc. Then we may need to find the elements we are interested, this process is interactive, since names of the element in ggplot2 are made by some numbers and text, they are not always meanful, after we identify the names of the element we are interested, we can use the grid.remove() function to remove the elements, blew is the sample code I made.

    library(grid)
    library(ggplot2)
    set.seed(1)
    data <- data.frame(x = rep(1:10, 2), y = sample(1:100, 20),
                       type = sample(c("A", "B"), 20, replace = TRUE))

    ggplot(data, aes(x = x, y =y,color = type))+
      geom_point()+
      geom_line()+
      scale_color_manual(values = c("blue", "darkred"))+
      theme_bw()

original picture

until now, we have finished draw the whole picture, then we need to do some works remove some elements in the picture.

    grid.force()
    grid.ls()

the elements names in picture

grid.ls() list all the element names

    grid.remove("key-4-1-1.5-2-5-2")
    grid.remove("key-4-1-2.5-2-5-2")
    grid.remove("label-4-3.5-4-5-4")

modified picture

xiaojia zhang
  • 928
  • 7
  • 8
  • When I try to use the grid functions on a ggplot object I get an error that its an invalid force target (with the grid.force()) function. Also, when I run the functions without any arguments they execute without any error but it also doesn't return any information regarding the underlying information. – Kreitz Gigs Apr 12 '19 at 05:23
0

It's not perfect, but my solution would be to actually make two plots and combine them together. See this post where I lifted the extraction code from.

I don't have your data, but I think you will get the idea below:

library(ggplot2)
library(gridExtra)
library(grid)

#g_table credit goes to https://stackoverflow.com/a/11886071/2060081

g_legend<-function(a.gplot){ 
tmp <- ggplot_gtable(ggplot_build(a.gplot)) 
leg <- which(sapply(tmp$grobs, function(x) x$name) == "guide-box") 
legend <- tmp$grobs[[leg]] 
return(legend)} 

p_legend = ggplot(dfwide[sp=='Overall Effects'], aes(x=Estimate, y=var, color=factor(sp), 
size=factor(rndm),
                   alpha=factor(rndm))) + 
  geom_point(position =pd) + 
  geom_errorbarh(aes(xmin=(`2.5%`), xmax=(`95%`)), position=pd, 
                     size=.5, height = 0, width=0) + 
  geom_vline(xintercept=0) + 
  scale_colour_manual(values=c("blue"), 
                      labels=c("Overall Effects"))) +
  scale_size_manual(values=c(3)) + 
  scale_shape_manual(labels="", values=c("1"=16,"2"=16)) + 
  scale_alpha_manual(values=c(1, 0.4)) + guides(size=FALSE, alpha=FALSE) + 
  ggtitle(label = "A.") + 
  scale_y_discrete(limits = rev(unique(sort(dfwide$var))), labels=estimates) + 
  ylab("") + 
  labs(col="Effects") + theme(legend.title=element_blank())

p_legend = g_legend(p_legend)

One of your plots will just be the legend. Subset your data based on the Overall Effects and then plot the two plots together as a grid.

sempervent
  • 833
  • 2
  • 11
  • 23