Reputation: 1146
The code below produces a contour plot using ggplot.
xgrid <- seq(min(mtcars$wt), max(mtcars$wt), 0.3)
ygrid <- seq(min(mtcars$hp), max(mtcars$hp), 0.3)
data.fit <- expand.grid(wt = xgrid, hp = ygrid)
data.loess <- loess(qsec ~ wt * hp, data = mtcars)
mtrx3d <- predict(data.loess, newdata = data.fit)
mtrx3d[1:4, 1:4]
require(reshape)
mtrx.melt <- melt(mtrx3d, id.vars = c("wt", "hp"), measure.vars = "qsec")
names(mtrx.melt) <- c("wt", "hp", "qsec")
require(stringr)
mtrx.melt$wt <- as.numeric(str_sub(mtrx.melt$wt, str_locate(mtrx.melt$wt, "=")[1,1] + 1))
mtrx.melt$hp <- as.numeric(str_sub(mtrx.melt$hp, str_locate(mtrx.melt$hp, "=")[1,1] + 1))
ggplot(mtrx.melt, aes(x = wt, y = hp, z = qsec)) + stat_contour()
I wonder how to show all acutal data points with the contour lines. I have tried
ggplot(mtrx.melt, aes(x = wt, y = hp, z = qsec)) +
stat_contour() + geom_point(mtrx.melt, aes(x = wt, y = hp, z = qsec))
but this returned an error message said
Error: ggplot2 doesn't know how to deal with data of class uneval
This is similar to this question how-can-i-overlay-points-and-lines-onto-a-contour-plot-with-ggplot2 but is based on different situation. In that question, op wants to annotate a contour plot with particular points that he wants to highlight (where these points are stored in a different data set). My case is to highlight all original data points in mtrx.melt
. I tried the method in that question but failed to work.
The plot above is not based on the dataset, it is just what I expect to have, I want to have a contour plot with its original data points.
Upvotes: 1
Views: 2708
Reputation: 42564
There are several issues which prevent to produce the desired result. Some of which are already mentioned in comments.
However, the OP wants to show the actual data points but is trying to plot the regular grid mtrx.melt
which is used to interpolate the data, instead.
The follwing code
library(ggplot2)
ggplot(mtrx.melt, aes(x = wt, y = hp, z = qsec))+
geom_point(aes(colour = qsec), mtcars) +
stat_contour(aes(colour = ..level..))
creates
which is probably what the OP is looking for.
Please, note
mtcars
data set are shown.geom_point()
and the like is different from ggplot
. The geoms and stats expect the aesthetic mapping
as first parameter and data
as second.geom_point()
is called before stat_contour()
to ensure that the legend title is qsec
instead of level
. Beware when replacing stat_contour()
by geom_tile()
. Then the tiles have to be plotted as first layer and the points on top.EDIT In response to this comment by the OP, the code could have been written as well as
ggplot(mapping = aes(x = wt, y = hp, z = qsec)) +
geom_point(aes(colour = qsec), mtcars) +
geom_contour(aes(colour = ..level..), mtrx.melt)
This makes it more explicit that two layers, i.e., geom_point()
and geom_contour()
, are being used to display data of two different data sources. The aesthetics which are shared between both layers are placed in the initial ggplot()
call (which is possible here because mtcars
and mtrx.melt
use the same column names). The colour
aesthetic is different, so each layer uses its own definition.
In the call to ggplot()
, it's now required to specify the parameter name mapping = aes(...)
because ggplot()
expects data
as first parameter if unnamed.
geom_contour()
is used here as the code appears more consistent and it seems to be preferred over stat_contour()
following the examples on the ggplot2
documentation site.
Upvotes: 1