Creating a continuous heat map in R

Viewed 21462

I have a series of x and y coordinates that each have a distance attached to them. I would like to create a heat map that displays the average distance for every point within the x and y ranges as a heat map. Since the points are not spaced evenly from each other in a lattice-like shape, the method would require some kind of smoothing function that clusters data and calculates the average for each point the vicinity and then representing that average with a color.

So far, using ggplot2, I can only find methods like stat_density2d and geom_tile, which only work for displaying point density and representing evenly spaced points (as far as I can tell).

Ideally it would follow the same principle as this image: enter image description here

in which colors were assigned based on the given points in the vicinity even though the density and placement of the points was not uniform.

I do not want to create a heat map in matrix form like this image: enter image description here

in which a table is color-coded. Instead, I would like to create a continuous heat map using non-uniformly distributed x and y coordinates that, in effect, displays the limit in which the data is broken into infinitely many rectangles. This may not be the actual method used by the function, but it provides a general idea as to what I'm looking for.

Here is some sample data:

data=data.frame(x=c(1,1,2,2,3,4,5,6,7,7,8,9),
  y=c(2,4,5,1,3,8,4,8,1,1,6,9),
  distance=c(66,84,93,76,104,29,70,19,60,50,46,36))

How can I make a heat map with distance as the color scale that covers the entire range of numbers, like the plot in the first link provided?

Any help is greatly appreciated!

4 Answers

using the akima::interp solution suggested by @plannapus, you can convert it to a ggplot2 heatmap.

Advantage of this ggplot2 solution is that you can easily add initial points with geom_point() or density curves with geom_density2d() (although here density will be unreliable with the 12 points you have).

library(akima)
library(tidyverse)
data <- data.frame(x=c(1,1,2,2,3,4,5,6,7,7,8,9),
                   y=c(2,4,5,1,3,8,4,8,1,1,6,9),
                   distance=c(66,84,93,76,104,29,70,19,60,50,46,36))
resolution <- 0.1 # you can increase the resolution by decreasing this number (warning: the resulting dataframe size increase very quickly)
a <- interp(x=data$x, y=data$y, z=data$distance, 
            xo=seq(min(data$x),max(data$x),by=resolution), 
            yo=seq(min(data$y),max(data$y),by=resolution), duplicate="mean")


res <- a$z %>% 
  magrittr::set_colnames(a$y) %>% 
  as_tibble() %>% 
  mutate(x=a$x) %>% 
  gather(y, z, -x, convert=TRUE)

res %>% 
  ggplot(aes(x, y)) +
  geom_tile(aes(fill=z)) +
  geom_point(data=data) +
  scale_fill_viridis_c()

Created on 2020-01-29 by the reprex package (v0.3.0.9001)

Related