基于一个数值,在R中使用ggmap生成空间热力图

4
我想使用以下数据点生成等值分布图:
  • 经度
  • 纬度
  • 价格
这是数据集 - https://www.dropbox.com/s/0s05cl34bko7ggm/sample_data.csv?dl=0
我想让地图显示价格较高和价格较低的区域。它应该像这样(样例图片): enter image description here 这是我的代码:
library(ggmap)

map <- get_map(location = "austin", zoom = 9)
data <- read.csv(file.choose(), stringsAsFactors = FALSE)
data$average_rate_per_night <- as.numeric(gsub("[\\$,]", "", 
data$average_rate_per_night))
ggmap(map, extent = "device") + 
stat_contour( data = data, geom="polygon", 
            aes( x = longitude, y = latitude, z = average_rate_per_night, 
fill = ..level.. ) ) +
scale_fill_continuous( name = "Price", low = "yellow", high = "red" )

我收到了以下错误信息:
2: Computation failed in `stat_contour()`:
Contour requires single `z` at each combination of `x` and `y`. 

我非常希望能够得到帮助,解决这个问题或找到其他方法来生成这种类型的热力图。请注意,我对价格的权重感兴趣,而不是记录的密度。


你确定你要找的是区域分布图吗?据我所知,大多数区域分布图使用行政区域,而不是纬度/经度。 - Jindra Lacko
我同意。我认为正确的术语应该是等高线地图。 - user709413
通过对每晚的费率进行平均值计算(某些 x 和 y 的组合可能由于坐标四舍五入而产生多个平均费率),我成功消除了“每个组合单一 z”错误信息。但等高线仍未绘制出来,我不知道原因也没有提示。等高线图适用于栅格,因此您可以通过将数据框架更改为栅格并替换缺失值来使其正常工作。我现在放弃了... - Jindra Lacko
2个回答

4
如果您坚持使用轮廓方法,则需要为数据中可能出现的每个x,y坐标组合提供一个值。为了实现这一点,我强烈建议对空间进行网格化,并生成每个bin的摘要统计信息。
以下是基于您提供的数据的工作示例:
library(ggmap)
library(data.table)

map <- get_map(location = "austin", zoom = 12)
data <- setDT(read.csv(file.choose(), stringsAsFactors = FALSE))

# convert the rate from string into numbers
data[, average_rate_per_night := as.numeric(gsub(",", "", 
       substr(average_rate_per_night, 2, nchar(average_rate_per_night))))]

# generate bins for the x, y coordinates
xbreaks <- seq(floor(min(data$latitude)), ceiling(max(data$latitude)), by = 0.01)
ybreaks <- seq(floor(min(data$longitude)), ceiling(max(data$longitude)), by = 0.01)

# allocate the data points into the bins
data$latbin <- xbreaks[cut(data$latitude, breaks = xbreaks, labels=F)]
data$longbin <- ybreaks[cut(data$longitude, breaks = ybreaks, labels=F)]

# Summarise the data for each bin
datamat <- data[, list(average_rate_per_night = mean(average_rate_per_night)), 
                 by = c("latbin", "longbin")]

# Merge the summarised data with all possible x, y coordinate combinations to get 
# a value for every bin
datamat <- merge(setDT(expand.grid(latbin = xbreaks, longbin = ybreaks)), datamat, 
                 by = c("latbin", "longbin"), all.x = TRUE, all.y = FALSE)

# Fill up the empty bins 0 to smooth the contour plot
datamat[is.na(average_rate_per_night), ]$average_rate_per_night <- 0

# Plot the contours
ggmap(map, extent = "device") +
  stat_contour(data = datamat, aes(x = longbin, y = latbin, z = average_rate_per_night, 
               fill = ..level.., alpha = ..level..), geom = 'polygon', binwidth = 100) +
  scale_fill_gradient(name = "Price", low = "green", high = "red") +
  guides(alpha = FALSE)

enter image description here

您可以调整箱子的大小和轮廓的binwidth来获得所需的结果,但您还可以在网格上应用平滑函数,以获得更平滑的等值线图。


这个很好用。我会尝试调整binwidth和箱子大小。 - user709413
1
我有一个问题 - 我们不应该将xbreaks和ybreaks视为经度和纬度吗?你能解释一下吗? - user709413
1
你可以这样做,但是你的数据并没有均匀地覆盖整个区域。这意味着你最终会得到大小不均匀的桶,因此等高线图可能不如示例中那么平滑。此外,使用建议的方法,你可以确保为所有的x、y组合提供等高线图数据。 - gcons
我认为你在示例中颠倒了x和y。纬度代表y轴,因为它代表南北位置。经度代表东西位置。 - Gene G.
能否使用收入和另一个变量制作这个热力图区域分布图? - stats_noob

2
您可以使用stat_summary_2d()stat_summary_hex()函数来实现类似的结果。这些函数将数据分成由x和y定义的bin,然后根据给定的函数总结每个bin的z值。在下面的示例中,我选择了平均值作为聚合函数,该地图基本上显示了每个bin中的平均价格。
注意:我需要适当处理您的average_rate_per_night变量,以便将其转换为数字(删除$符号和逗号)。
library(ggmap)
library(data.table)

map <- get_map(location = "austin", zoom = 12)
data <- setDT(read.csv(file.choose(), stringsAsFactors = FALSE))
data[, average_rate_per_night := as.numeric(gsub(",", "",
    substr(average_rate_per_night, 2, nchar(average_rate_per_night))))]

ggmap(map, extent = "device") +
    stat_summary_2d(data = data, aes(x = longitude, y = latitude, 
        z = average_rate_per_night), fun = mean, alpha = 0.6, bins = 30) +
    scale_fill_gradient(name = "Price", low = "green", high = "red") 

enter image description here


谢谢您的帮助,但我正在寻找类似于这样的东西 - https://sromalewski.files.wordpress.com/2011/09/bike-share-station-suggestions-091911-913x1024.png - user709413

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接