基于一个值,在R中通过ggmap生成空间热图。

时间:2022-11-20 22:48:47

I'd like to generate a choropleth map using the following data points:

我想用以下的数据点生成一个等值线图:

  • Longitude
  • 经度
  • Latitude
  • 纬度
  • Price
  • 价格

Here is the dataset - https://www.dropbox.com/s/0s05cl34bko7ggm/sample_data.csv?dl=0.

这是数据集——https://www.dropbox.com/s/0s05cl34bko7ggm/sample_data.csv?

I would like the map to show the areas where the price is higher and the where price is lower. It should most probably look like this (sample image):

我想要这张地图显示价格较高和价格较低的地区。它很可能是这样的(样本图像):

基于一个值,在R中通过ggmap生成空间热图。

Here is my code:

这是我的代码:

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" )

I'm getting the following error message:

我得到以下错误信息:

2: Computation failed in `stat_contour()`:
Contour requires single `z` at each combination of `x` and `y`. 

I'd really appreciate any help on how this can be fixed or any other method to generate this type of heatmap. Please note that I'm interested in the weight of the price, not density of the records.

我非常感谢任何关于如何修复这一点的帮助,或者任何其他方法来生成这种类型的热图。请注意,我感兴趣的是价格的重量,而不是记录的密度。

2 个解决方案

#1


2  

If you insist on using the contour approach then you need to provide a value for every possible x,y coordinate combination you have in your data. To achieve this I would highly recommend to grid the space and generate some summary statistics per bin.

如果您坚持使用轮廓方法,那么您需要为数据中的每一个可能的x、y坐标组合提供一个值。为了实现这一点,我强烈建议对空间进行网格化,并生成每个bin的一些汇总统计信息。

I attach a working example below based on the data you provided:

根据你提供的数据,我附上一个工作示例:

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)

基于一个值,在R中通过ggmap生成空间热图。

You can then play around with the bin size and the contour binwidth to get the desired result but you could additionally apply a smoothing function on the grid to get an even smoother contour plot.

然后您可以使用bin大小和轮廓binwidth来获得想要的结果,但是您可以在网格上使用平滑函数来获得更平滑的等高线图。

#2


0  

You could use the stat_summary_2d() or stat_summary_hex() function to achieve a similar result. These functions divide the data into bins (defined by x and y), and then the z values for each bin are summarised based on a given function. In the example below I have selected mean as an aggregation function and the map basically shows the average price in each bin.

您可以使用stat_summary_2d()或stat_summary_hex()函数来实现类似的结果。这些函数将数据划分为bin(由x和y定义),然后根据给定的函数总结每个bin的z值。在下面的例子中,我选择了mean作为聚合函数,而map基本上显示了每个bin中的平均价格。

Note: I needed to treat your average_rate_per_night variable appropriately in order to convert it into numbers (removed the $ sign and the comma).

注意:我需要适当地处理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") 

基于一个值,在R中通过ggmap生成空间热图。

#1


2  

If you insist on using the contour approach then you need to provide a value for every possible x,y coordinate combination you have in your data. To achieve this I would highly recommend to grid the space and generate some summary statistics per bin.

如果您坚持使用轮廓方法,那么您需要为数据中的每一个可能的x、y坐标组合提供一个值。为了实现这一点,我强烈建议对空间进行网格化,并生成每个bin的一些汇总统计信息。

I attach a working example below based on the data you provided:

根据你提供的数据,我附上一个工作示例:

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)

基于一个值,在R中通过ggmap生成空间热图。

You can then play around with the bin size and the contour binwidth to get the desired result but you could additionally apply a smoothing function on the grid to get an even smoother contour plot.

然后您可以使用bin大小和轮廓binwidth来获得想要的结果,但是您可以在网格上使用平滑函数来获得更平滑的等高线图。

#2


0  

You could use the stat_summary_2d() or stat_summary_hex() function to achieve a similar result. These functions divide the data into bins (defined by x and y), and then the z values for each bin are summarised based on a given function. In the example below I have selected mean as an aggregation function and the map basically shows the average price in each bin.

您可以使用stat_summary_2d()或stat_summary_hex()函数来实现类似的结果。这些函数将数据划分为bin(由x和y定义),然后根据给定的函数总结每个bin的z值。在下面的例子中,我选择了mean作为聚合函数,而map基本上显示了每个bin中的平均价格。

Note: I needed to treat your average_rate_per_night variable appropriately in order to convert it into numbers (removed the $ sign and the comma).

注意:我需要适当地处理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") 

基于一个值,在R中通过ggmap生成空间热图。