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.
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:
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
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.