【问题标题】:r heatmap - stat_density2d (ggmap) vs. addHeatmap (shiny leaflet)r 热图 - stat_density2d(ggmap)与 addHeatmap(闪亮传单)
【发布时间】:2017-11-28 16:21:12
【问题描述】:

我使用library(ggmap)stat_density2d() 函数制作了静态热图。为了在动态leaflet 地图上的闪亮应用程序中重新创建它,我找到了addHeatmap()。但是,生成的图像是不同的,ggmap 版本似乎提供了正确的结果。

GGMAP

传单

造成这种差异的原因是什么?

要运行以下两个可重现的示例,您可以下载我放在这里的一些数据(csv 文件)。 https://drive.google.com/drive/folders/0B8_GTHBuoKSRR1VIRmhOUTJKYU0?usp=sharing

请注意,leaflet 结果因缩放级别而异,但绝不与ggmap 结果匹配(例如,就最大热量的位置而言)。

这是ggmap 代码。

library(ggmap)
data <- read.csv("DATA.csv", sep=";")
data <- subset(data, !is.na(CrdLatDeg))
xmin <- min(data$CrdLonDeg)
xmax <- max(data$CrdLonDeg)
ymin <- min(data$CrdLatDeg)
ymax <- max(data$CrdLatDeg)
lon <- c(xmin,xmax)
lat <- c(ymin,ymax)
map <- get_map(location = c(lon = mean(lon), lat = mean(lat)), zoom = 17,
               maptype = "satellite", source = "google")
ggmap(map) + 
  labs(x="longitude", y="latitude") + 
  stat_density2d(data=data, aes(x=CrdLonDeg, y=CrdLatDeg, alpha= ..level.., fill= ..level..), colour=FALSE,
                 geom="polygon", bins=100) + 
  scale_fill_gradientn(colours=c(rev(rainbow(100, start=0, end=.7)))) + scale_alpha(range=c(0,.8)) + 
  guides(alpha=FALSE,fill=FALSE)

这是leaflet 代码。

library(leaflet.extras)
data <- read.csv("DATA.csv", sep=";")
data <- subset(data, !is.na(CrdLatDeg))
leaflet(data) %>%
  addTiles(group="OSM") %>%
  addHeatmap(group="heat", lng=~CrdLonDeg, lat=~CrdLatDeg, max=.6, blur = 60)

【问题讨论】:

  • 图像看起来如何?不看它们很难区分。
  • @IvanSanchez:我提供了数据和代码,你应该可以自己制作图像吗?我(还)不允许在此处嵌入图像,因此我将图像结果上传到我放置数据的同一个链接。
  • 就我个人而言,我知道 Leaflet 和 heatmap 算法,但不知道关于 R 的第一件事。运行示例意味着花时间运行示例。拥有数据和代码是一件非常好的事情,但如果可以的话,你应该让其他人更容易看到问题。如果您将图片上传到某个地方,我将能够编辑您的帖子并将其包含在内。
  • 好吧,就像我说的,他们在同一个 Google Drive 链接后面。感谢您的宝贵时间。
  • 嗯,你确实没有提到谷歌驱动器链接有图像,至少当我读到这个时:-P

标签: r shiny leaflet heatmap ggmap


【解决方案1】:

我在 GIS 上找到了this answer,我尝试创建一个函数并将其应用于此案例。到目前为止,我还没有弄清楚如何微调颜色渐变方案,但它似乎是一个不错的开始:

library(leaflet)
library(rlang)

addHeatMap <- function(data, lon, lat, intensity, show.legend, ...) {
  df <- data.table::as.data.table(data)
  df_expanded <- dplyr::slice(df, rep(1:dplyr::n(), times = !! enquo(intensity)))

  lon_var <- dplyr::pull(df_expanded, !! enquo(lon))
  lat_var <- dplyr::pull(df_expanded, !! enquo(lat))

  lon_bw <- MASS::bandwidth.nrd(lon_var)
  lat_bw <- MASS::bandwidth.nrd(lat_var)

  lon_lat_df <- dplyr::select(df_expanded, !! enquo(lon), !! enquo(lat))

  kde <- KernSmooth::bkde2D(lon_lat_df, bandwidth = c(lon_bw, lat_bw))
  CL <- contourLines(kde$x1 , kde$x2 , kde$fhat)
  LEVS <- as.factor(sapply(CL, `[[`, "level"))
  NLEV <- nlevels(LEVS)
  pgons <- lapply(1:length(CL), function(i)
  sp::Polygons(list(sp::Polygon(cbind(CL[[i]]$x, CL[[i]]$y))), ID = i))
  spgons <- sp::SpatialPolygons(pgons)

  if (show.legend) {
    leaflet::addPolygons(data = spgons, color = heat.colors(NLEV, NULL)[LEVS], stroke = FALSE, ...) %>% 
      leaflet::addLegend(colors = heat.colors(NLEV, NULL)[LEVS], labels = LEVS)
    } else {
    leaflet::addPolygons(data = spgons, color = heat.colors(NLEV, NULL)[LEVS], stroke = FALSE, ...)
    }
}

mydata <- read.csv("DATA.csv", sep=";")
mydata <- subset(mydata, !is.na(CrdLatDeg))

leaflet() %>%
  addTiles(group = "OSM") %>%
  addHeatMap(data = mydata, lon = CrdLonDeg, lat = CrdLatDeg, intensity = FsmIdf, show.legend = TRUE)

【讨论】:

  • 你能检查一下你的功能吗?我正在尝试重现它,但我不明白什么是“强度”。对象Fsmdf 之前没有声明过。提前致谢!
  • 是OP提供的数据文件中的一个变量。
  • 但是变量是什么?它是一个ID?为了创建热图,扮演什么角色?
  • OP 想要将“热”强度水平集中在特定的纬度/经度点上。我不知道那个变量代表什么。
  • @Phil:你的代码太棒了!这里较深的颜色是否代表变量“fsmidf”的较大值?是否可以添加一个图例来指示与“fsmidf”的颜色和范围的关联?
【解决方案2】:

图像看起来不同,因为算法不同。

stat_density2d() 从离散数据中推断出probability density function

热图的传单实现依赖于 simpleheatheatmap.jswebgl-heatmap 等库。这些热图依赖于概率密度。 (我不完全确定 r-leaflet 的 addHeatmap 使用了哪些)。

相反,这些热图的工作原理是为每个点绘制一个模糊的圆圈,将每个像素的值提高一个与点的强度成正比的量(在您的情况下为常数),与点之间的距离成反比和圆圈。每个数据点在热图中显示为一个圆圈。您可以通过在the heatmap.js webpage 中使用鼠标光标来查看这一点,或者查看图片右上角的这个单独的点:

将热图想象成函数的可视化

f(pixel) = ∑ ( max( 0, 半径 - 距离(pixel, point) ) · 强度(point) )

可以调整热图的半径和强度,但结果永远不会与统计密度估计相同。

【讨论】:

【解决方案3】:

两者都使用不同的算法。您需要调整addHeatmapradiusblur 参数以及stat_density2dh 参数以获得相似的结果。

【讨论】:

  • 好吧,我已经做了很多调整,但它们看起来一点也不像。我想要一个显示点密度的leaflet 选项。这似乎不会在我当前使用 addHeatmap 时发生,因为它以最暖的颜色(红色)突出显示密度小于最大密度的区域,似乎与提供给参数的值无关。
猜你喜欢
  • 1970-01-01
  • 2021-08-04
  • 2018-06-19
  • 1970-01-01
  • 2020-04-14
  • 1970-01-01
  • 1970-01-01
  • 2015-05-08
  • 1970-01-01
相关资源
最近更新 更多