0

Following code plots a math function as a heatmap (from: How to plot a maths function as a heatmap):

xvec <- yvec <- seq(0,10,length.out=41)
z <- outer(xvec,yvec,function(x,y) x*y^2)
image(xvec,yvec,z)

How can I create this using ggplot2 geom_tile() ?

Following commands do not work:

ggplot()+geom_tile(aes(x=xvec, y=yvec, z=z))

and

zdf = data.frame(z)
ggplot(zdf)+geom_tile(aes(z=zdf))

I am surprised not to find similar question on searching. Thanks for your help.

Community
  • 1
  • 1
rnso
  • 23,686
  • 25
  • 112
  • 234

2 Answers2

2

You need to arrange the X/Y coordinates and the data (z in your case) into a data.frame instead of a matrix.

For example:

xvec <- yvec <- seq(0,10,length.out=41)
df <- expand.grid(xvec, yvec)
df$z <- apply(df, 1, function(p) p[1] * p[2]^2)

head(df)

#   Var1 Var2 z
# 1 0.00    0 0
# 2 0.25    0 0
# 3 0.50    0 0
# 4 0.75    0 0
# 5 1.00    0 0
# 6 1.25    0 0

library(ggplot2)
ggplot(df) + geom_tile(aes(x=Var1, y=Var2, fill=z))

And you get:

enter image description here

Xin Yin
  • 2,896
  • 21
  • 20
2

You could also reshape your outer results with

xvec <- yvec <- seq(0,10,length.out=41)
z <- outer(xvec,yvec,function(x,y) x*y^2)

ggplot(data.frame(xvec=xvec[row(z)], yvec=yvec[col(z)], z=as.numeric(z))) + 
    geom_tile(aes(x=xvec, y=yvec, fill=z))

What we are doing here is building a new data.frame with triplets of values to plot: (x,y,color). The problem is we have length(xvec) rows and length(yvec) columns but length(xvec) * length(yvec) actual observations. So this trick will repeat the row and column values to make them the same length as the z values. Since z is a matrix, row(z) will give the row number for each value in z. We use this to repeat the xvec values multiple times and keep them insync with the z values. Same goes for the yvec values but we match those up to the columns of z. This is another way to create a data.frame in the form

  xvec yvec z
1 0.00    0 0
2 0.25    0 0
3 0.50    0 0
4 0.75    0 0
5 1.00    0 0
6 1.25    0 0
MrFlick
  • 195,160
  • 17
  • 277
  • 295
  • It works but change in data is difficult to understand. – rnso Aug 14 '14 at 03:44
  • I tried to add some further explanation. But if your data isn't already in a matrix, then the `expand.grid` option probably would be best for you. – MrFlick Aug 14 '14 at 03:48