5

I am trying to use putplot to change the plots on the diagonal of a ggpairs plot. I can do this one by one, but when I use a loop the diagonal elements are the same!

library(ggplot2)
library(GGally)

p=ggpairs(iris, 
    columns=, c("Sepal.Length", "Sepal.Width", "Petal.Length", "Petal.Width"),
    colour='Species',
    lower=list(continuous='points'), 
    axisLabels='none',  
    upper=list(continuous='blank')
)

for (i in 1:4) {
    p <- putPlot(p, ggplot(iris, aes(x=iris[,i], colour=Species)) + stat_ecdf(), i,i)
}
print(p)

Non working example

Unwinding the loop works... why...?

p <- putPlot(p, ggplot(iris, aes(x=iris[,1], colour=Species)) + stat_ecdf(), 1,1)
p <- putPlot(p, ggplot(iris, aes(x=iris[,2], colour=Species)) + stat_ecdf(), 2,2)
p <- putPlot(p, ggplot(iris, aes(x=iris[,3], colour=Species)) + stat_ecdf(), 3,3)
p <- putPlot(p, ggplot(iris, aes(x=iris[,4], colour=Species)) + stat_ecdf(), 4,4)

Working example

llrs
  • 3,308
  • 35
  • 68
bytesinflight
  • 1,624
  • 2
  • 17
  • 28

1 Answers1

4

This is the result of so-called lazy evaluation in ggplot. The calls to the various ggplot functions do not actually create a plot, they define how the plot is to be rendered. The plot is only created with, e.g., print(p).

The issue is that the arguments to aes(...) are stored as expressions in the plot definition, and those expressions are only evaluated when you render the plot. So in your case the four calls to ggplot are all stored the same way, with x=iris[,i]. When you render the plot, i=4 and all four diagonal slots are rendered with x=iris[,4].

So how to deal with this? We have to put the definition of x outside the call to aes(...). This code accomplishes that:

for (i in 1:4) {
  p <- putPlot(p,ggplot(data=data.frame(x=iris[,i],Species=iris$Species), 
                        aes(x=x,colour=Species)) + stat_ecdf(), i,i)
}
print(p)

Here we are setting the default dataset for ggplot to a different data frame in each plot using the appropriate column of iris for x. The reason this works is that the refenrece to x=iris[,i] is not in the call to aes(...).

See this link for a closely related problem, with a nearly identical solution.

Community
  • 1
  • 1
jlhoward
  • 58,004
  • 7
  • 97
  • 140