Search code examples
rggplot2ggtree

passing arguments to geom_point2 with mapply


My objective is pass lists as arguments to the function geom_point2 using lapply or analogously mapply. In similar situations, I had success passing a list (or lists) to geom_cladelabel as in:

mapply(function (x,y,z,w,v,u,t,s) geom_cladelabel(node=x, label=y,
align=F, etc. # Where x y z etc are lists. 

Problem is related to the use of aes inside geom_point2. (not in geom_cladelabel):

In the case of geom_point2, the node info is inside aes, and I could't do it. Normally I do not get any error message, but it does not work.

The objective is to make this example work, but using mapply instead of writting geom_point2 two times.

# source("https://bioconductor.org/biocLite.R")
# biocLite("ggtree")
library(ggtree)
library(ape)
#standard code
newstree<-rtree(10)
node1<-getMRCA(newstree,c(1,2))
node2<-getMRCA(newstree,c(3,4))
ggtree(newstree)+ 
geom_point2(aes(subset=(node ==node1) ), fill="black", size=3, shape=23)+
geom_point2(aes(subset=(node ==node2) ), fill="green", size=3, shape=23)

#desire to substitute the geom_point2 layers with mapply or lapply:
#lapply(c(node1,node2), function (x) geom_point2(aes(subset=(node=x)))))

enter image description here


Solution

  • Here is a solution calling geom_point2 usig mapply:

    library(ggtree)
    ggtree(rtree(10)) + 
      mapply(function(x, y, z) 
        geom_point2(
          aes_string(subset=paste("node ==", x)), 
          fill=y, 
          size=10, 
          shape=z
        ), 
        x=c(11,12), 
        y=c("green", "firebrick"), 
        z=c(23,24)
      ) +
      geom_text2(aes(subset=!isTip, label=node)) 
    

    The solution is in the aes_string(), which writes the value of x directly in the aesthetics. The default aes() does not pass on the value of x, but just the string "x". When plotting, ggtree then looks for a node called "x", and ends with an empty node list. I guess this has to do with the variable being stored in the mapply-environment and not being passed on to the plot.

    PS: Sorry for my too quick answer with do.call() earlier. It is useful, but off-topic here.