Here is a toy version of my problem
x = runif(10);
y = runif(10);
z = (x+y)*(x-y);
I would like to then generate a heatmap of z vs. (x+y) and (xy). The problem is that z is a vector and is not defined over all combinations of y and x. Please note I am not looking for an answer that generates z for these missing values , that is not a possibility in the real version of the problem. This is just a minimal version to work with. All solutions I've been able to find, such as filled.contour
need a matrix for z specified over a grid of the independent variables rather than just a set of (x,y,z) data points with no structure per se .
Package akima
has what you need. It does bivariate interpolation with interp
. It does generate z values for the missing combinations, but couldnt you just exclude those if you wanted to? If you aren't generating z-values just plot a 3d scatter of z ~ x*y.
x = runif(10);
y = runif(10);
z = (x+y)*(x-y);
library(akima)
dens <- interp(x+y, x-y, z,
xo=seq(min(x+y), max(x+y), length=100),
yo=seq(min(x-y), max(x-y), length=100),
duplicate="median")
filled.contour(dens, xlab="x+y", ylab="x-y", main="z",
color.palette = heat.colors)
If you are truly set on not interpolating, to add to the ggplot options provided by @Frank, there are a number of aesthetics you can use to contrast points by a third dimension.
library(ggplot2)
dat <- data.frame(x1=x+y, x2=x-y, z=z)
## Scaling points by z dimension using size, color, and shading
ggplot(dat, aes(x1, x2, size=z, alpha=z, color=z)) +
geom_point() +
scale_color_gradient(low="red", high="yellow") +
theme_bw()
Here is a possibility with ggplot2
where I do not generate values for z when they are "missing", unlike the answer using interpolation..
set.seed(54321)
x = runif(10)
y = runif(10)
z = (x+y)*(x-y)
ggplot(df, aes(x+y, x-y, fill=z)) +
scale_fill_gradient(low = "blue", high = "red") + geom_tile()
You can force/manipulate the tile size and overall appearance by using round
or cut
:
ggplot(df, aes(round(x+y,1),round(x-y,1), fill=z)
scale_fill_gradient(low = "blue", high = "red") +
geom_tile()
# OR
ggplot(df, aes(cut(x+y, 15), cut(x-y, 15), fill=z))
scale_fill_gradient(low = "blue", high = "red") +
geom_tile() +
theme(axis.text.x=element_blank(), axis.text.y=element_blank())
Maybe the most simple way to achieve a result that resembles what I believe is the requested output could consist in using the lattice
package:
set.seed(12358)
x <- runif(10)
y <- runif(10)
z <-(x+y)*(x-y)
x1<-x+y
y1<-x-y
library(lattice)
df<-data.frame(x=x1,y=y1,z=z)
levelplot(z~x1*y1,df,cuts=9,col.regions=grey.colors(10)[10:1])
But admittedly, this does not look very pretty. Probably a better way to represent the data is an interactive 3D-scatterplot, which can be generated with the rgl
package, as shown below. For this chart I used a function from the "R Graphics Cookbook" by Winston Chang to draw the vertical blue lines:
library(rgl)
plot3d(x1,y1,z, size=1,type="s")
interleave <- function(v1,v2) as.vector(rbind(v1,v2))
segments3d(interleave(x1,x1), interleave(y1,y1), interleave(z,0),alpha=0.4,col="blue")
planes3d(a=0,b=0,c=1,d=0,alpha=0.1)
Since the OP stated very clearly that no interpolation was desired, I refrain from posting simple possibilities to display such continuous heatmaps, even though I think that for such a type of data set it usually makes sense to interpolate the data.
In fact, I have some difficulties in understanding the use of a heatmap (which in my opinion is inherently a 2D object) applied to a structureless set of disconnected points.
Here is a variation with base plot:
x = runif(10);
y = runif(10);
z = (x+y)*(x-y);
n = 5
zz = cut(z, n)
cols <- heat.colors(n)
plot(x, y, col=cols[zz], cex=4, pch=20)
legend('topright', legend=levels(zz), pch=20, col=cols, pt.cex=3)
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.