2017-07-26 76 views
3

我想使用以下的数据点,以产生等值线图:生成通过基于值中的R ggmap空间热图

  • 经度
  • 纬度
  • 价格

这里是数据集 - 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`. 

我对于如何解决这个问题,或者其他方法来生成这种类型的热图,我真的很感激。请注意,我对价格的重量感兴趣,而不是记录的密度。

+0

你确定你在找choropleth吗?据我所知,大多数人群使用行政区域,而不是经度/经度。 –

+0

我同意。我认为正确的术语应该是等高线图。 – user709413

+0

我可以通过平均每晚的费率(一些x和y组合有多个平均费率,我想是因为四舍五入关闭)而摆脱了每个组合的单个z错误消息。但轮廓仍然没有画出。我不知道为什么,也没有说。等值线图对栅格起作用,所以您可以通过将数据框更改为栅格并替换缺失值来使其工作。我现在放弃... –

回答

2

如果你坚持使用轮廓的方法,那么你需要为每一个可能的X提供一个值,y坐标数据中的你有组合。为了达到这个目的,我强烈建议网格化空间并为每个容器生成一些汇总统计信息。

我附上下面的工作示例根据您所提供的数据:

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得到想要的结果,但您还可以在网格上应用平滑函数来获得更平滑的等高线图。

+0

这很好。我会玩'binwidth'和bin大小。 – user709413

+0

我有一个问题 - 我们不应该把xbreaks和ybreak作为经度和纬度吗?你能解释一下吗? – user709413

+1

你可以但你的数据不统一覆盖整个区域。这意味着你最终会得到不均匀大小的桶,因此轮廓图可能不如示例中那样平滑。另外使用建议的方法,您可以确保为所有x,y组合提供等值线图数据。 – gcons

0

您可以使用stat_summary_2d()stat_summary_hex()功能,以达到类似的结果。这些函数将数据划分为bin(由x和y定义),然后根据给定函数汇总每个bin的z值。在下面的例子中,我选择mean作为聚合函数,地图基本显示每个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

+0

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