简体   繁体   中英

Function to plot pairs() variables against common vertical axis variable in the diagonal

I am trying to define a function to produce a scatterplot across the diagonal of a pairs plot. The trick is that I'd like to specify the vertical axis probably in the panel.splot function. Ultimately I think the use here is to visualize a time series on the diagonal. For a simple example though I'd like to try this with the iris dataset and use Species as the vertical axis variable. The plot below produces a nice looking plot:

pairs(iris[,c(1:4)])

So now I'd need to define a function for the diagonal panel. Here is my efforts so far:

panel.splot <- function(x, yvar,...)
{
  usr <- par("usr"); on.exit(par(usr))
  par(usr = c(0, 2, usr[3:4]))
  plot(yvar,x, xlim=c(min(x),max(x)))
}

However, when I try to run it, I get an error message that I'm not sure how to interpret.

pairs(iris[,c(1:4)],diag.panel=panel.splot(x=x, yvar="Species"))

Error in plot.window(...) : invalid 'xlim' value
In addition: Warning messages:
1: In xy.coords(x, y, xlabel, ylabel, log) : NAs introduced by coercion
2: In xy.coords(x, y, xlabel, ylabel, log) : NAs introduced by coercion
3: In min(x) : no non-missing arguments to min; returning Inf
4: In max(x) : no non-missing arguments to max; returning -Inf

I haven't been able to find another example of this. Lots of other functions to create different types of plots but nothing that does exactly this.

For clarity, this is the type of plot I am imagining would be produced along the diagonal of the pairs() call:

plot(iris$Species,iris$Petal.Width)

Following rawr recommendations, I managed to get your plot:

panel.splot <- function(y)
{
        function(x,yv=y)
        {
                usr <- par("usr"); on.exit(par(usr))
                par(usr = c(0, 2, usr[3:4]), new = TRUE)
                plot(yv,x)
        }
}
pairs(iris[,1:4],diag.panel=panel.splot(iris[,5]))

在此输入图像描述

You'll still have to deal with text size

Despite your example plot, i interpreted this slightly differently (incorrectly) due to use Species as the vertical axis variable . Hubert's given the answer but thought it might add something.

Using pairs()

panel.splot <- function(Y, Adjust=0.2){
                    function(x, y=Y, adjust=Adjust)
                    {
                     usr <- par("usr"); on.exit(par(usr))
                     xs <- range(x)
                     ys <- if(is.factor(y)) c(1, nlevels(y)) else range(y)
                     par(usr = c(xs[1], xs[2], ys[1], ys[2]) + c(-adjust, adjust))
                     points(x, y)
                    }
                 }

pairs(iris[, 1:4], diag.panel=panel.splot(Y=iris$Species))

Which produces

在此输入图像描述

To do the same thing with ggpairs() you can also define a user function

library(GGally)
library(ggplot2)    

# Define diagonal function
diag_fun <- function(data, mapping, ...){
      ggplot(data = data, mapping = mapping) + 
      geom_point(...) 
      }

ggpairs(iris, columns=1:4, 
        diag = list(continuous = diag_fun, mapping=aes(y=Species)))

Which gives

在此输入图像描述


Update for your comments...

Yes, for the diagonal entries, the variable is passed as the x mapping. You can either use coord_flip() or reverse the mapping in the function. The function below does this, and adds the variable names using annotate() (ps. you should be able to swap out the _point geom for say, _boxplot

diag_fun <- function(data, mapping, xnudge=0.95, ynudge=1, pts=lst(), ...){

    # create range for annotate
    lbl <- as.character(mapping$x)
    xmax <- max(data[, as.character(mapping$x)], na.rm=TRUE)
    ymax <- mean(seq(nlevels(data[,as.character(mapping$y)]))) 

    # reverse mapping so no need for coord_flip() 
    tmp <- mapping$y
    mapping$y <- mapping$x
    mapping$x <- tmp

    ggplot(data=data, mapping=mapping) + 
      do.call(geom_point, pts) +
      annotate("text", x=ynudge*ymax, y=xnudge*xmax, label=lbl, ...)
      }

So to use it in ggpairs with the defaults

ggpairs(iris, columns=1:4,  diag = list(continuous = diag_fun, mapping=aes(y=Species)))

And you can use wrap to pass further arguments

ggpairs(iris, columns=1:4,  
        diag = list(continuous = 
                      wrap(diag_fun, 
                           size=10, col="red", # make changes to the text label
                           pts=list(colour="blue")), # make changes to geom_point
                    mapping=aes(y=Species))) 

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM