我想使用类似于
ggplot2
和ggmap
的工具,用于生成任意值的热力图,例如每平方米的房产价格,在高分辨率下以街道级别覆盖地理区域。不幸的是,这项任务似乎相当困难,因为虽然ggplot2
可以生成很好的密度图,但似乎无法在没有先前插值的情况下可视化此类空间数据。为此,我使用了akima
库(不规则数据的网格双变量插值)和mgcv
库(带有集成平滑度估计的广义加性模型),但我的插值方法知识最多只能算中等水平,我能够产生的结果还不够令人满意。请考虑以下示例:library(ggplot2)
library(ggmap)
## data simulation
set.seed(1945)
df <- tibble(x = rnorm(500, -0.7406, 0.03),
y = rnorm(500, 51.9976, 0.03),
z = abs(rnorm(500, 2000, 1000)))
地图、散点图、密度图
## ggmap
map <- get_map("Bletchley Park, Bletchley, Milton Keynes", zoom = 13, source = "stamen", maptype = "toner-background")
q <- ggmap(map, extent = "device", darken = .5)
## scatterplot over map
q + geom_point(aes(x, y), data = df, colour = z)
## classic density heat map
q +
stat_density2d(aes(x=x, y=y, fill=..level..), data=df, geom="polygon", alpha = .2) +
geom_density_2d(aes(x=x, y=y), data=df, colour = "white", alpha = .4) +
scale_fill_distiller(palette = "Spectral")
正如您所看到的,所选区域的数据相当密集,密度热力图具有圆形边缘和封闭曲线(除了一些最外层)。
使用akima进行插值和绘图
## akima interpolation
library(akima)
df_akima <-interp2xyz(interp(x=df$x, y=df$y, z=df$z, duplicate="mean", linear = T,
xo=seq(min(df$x), max(df$x), length=200),
yo=seq(min(df$y), max(df$y), length=200)), data.frame=TRUE)
## akima plot
q +
geom_tile(aes(x = x, y = y, fill = z), data = df_akima, alpha = .4) +
stat_contour(aes(x = x, y = y, z = z, fill = ..level..), data = df_akima, geom = 'polygon', alpha = .4) +
geom_contour(aes(x = x, y = y, z = z), data = df_akima, colour = 'white', alpha = .4) +
scale_fill_distiller(palette = "Spectral", na.value = NA)
这会产生一组插值数密集的网格(以确保足够的分辨率),虽然图底下的瓷砖绘图是可接受的,但轮廓绘图过于粗糙,许多曲线没有闭合。
使用linear = F
的非线性插值更加平滑,但显然会牺牲分辨率并且在数字(z
的负值)方面变得不稳定。
使用mgcv进行插值和绘图
## mgcv interpolation
library(mgcv)
gam <- gam(z ~ s(x, y, bs = 'sos'), data = df)
df_mgcv <- data.frame(expand.grid(x = seq(min(df$x), max(df$x), length=200),
y = seq(min(df$y), max(df$y), length=200)))
resp <- predict(gam, df_mgcv, type = "response")
df_mgcv$z <- resp
## mgcv plot
q +
geom_tile(aes(x = x, y = y, fill = z), data = df_mgcv, alpha = .4) +
stat_contour(aes(x = x, y = y, z = z, fill = ..level..), data = df_mgcv, geom = 'polygon', alpha = .4) +
geom_contour(aes(x = x, y = y, z = z), data = df_mgcv, colour = 'white', alpha = .4) +
scale_fill_distiller(palette = "Spectral", na.value = NA)
使用mgcv
进行相同的过程会得到一个漂亮而平滑的图形,但分辨率要低得多,并且实际上所有曲线都不闭合。
问题
请问您能否提供更好的方法或修改我的尝试,以获得类似第一个图的绘图(干净、连贯、平滑的线条,高分辨率)?
是否有可能关闭曲线,例如在最后一张图中(阴影区域应计算超出图像边界)?
感谢您的时间!