Генерация пространственной тепловой карты через ggmap в R на основе значения

Я хотел бы создать картограмму, используя следующие точки данных:

  • Долгота
  • Широта
  • Цена

Вот набор данных: https://www.dropbox.com/s/0s05cl34bko7ggm/sample_data.csv?dl=0.

Я хотел бы, чтобы на карте были показаны районы, где цена выше, а где цена ниже. Скорее всего, это должно выглядеть так (пример изображения):

введите здесь описание изображения

Вот мой код:

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`. 

Я был бы очень признателен за любую помощь в том, как это можно исправить, или за любой другой метод создания тепловой карты такого типа. Обратите внимание, что меня интересует вес цены, а не плотность записей.


person user709413    schedule 26.07.2017    source источник
comment
Вы уверены, что ищете хороплет? Насколько я знаю, в большинстве картограмм используются административные регионы, а не широта/долгота.   -  person Jindra Lacko    schedule 26.07.2017
comment
Я согласен. Я думаю, что правильный термин должен быть контурная карта.   -  person user709413    schedule 26.07.2017
comment
Мне удалось избавиться от сообщения об ошибке single z at each combination, усредняя скорость за ночь (некоторые комбинации x и y имели несколько средних скоростей, я полагаю, из-за округления координат). Но контур все равно не нарисовал. Я не знаю, почему, и это не сказал. График контурных линий работает для растров, поэтому вы можете заставить его работать, изменив фрейм данных на растр и заменив отсутствующие значения. сдаюсь пока...   -  person Jindra Lacko    schedule 27.07.2017


Ответы (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)

введите здесь описание изображения

Затем вы можете поиграть с размером интервала и шириной интервала контура, чтобы получить желаемый результат, но вы можете дополнительно применить функцию сглаживания к сетке, чтобы получить еще более плавный график контура.

person gcons    schedule 27.07.2017
comment
Это хорошо работает. Я поиграюсь с binwidth и размером корзины. - person user709413; 28.07.2017
comment
У меня есть один вопрос - не должны ли мы принимать xbreaks и ybreaks как долготу и широту? Не могли бы вы объяснить? - person user709413; 29.07.2017
comment
Вы могли бы, но ваши данные не охватывают равномерно всю область. Это означает, что в конечном итоге у вас будут ведра разного размера, и поэтому контурный график может быть не таким гладким, как в примере. Кроме того, используя предлагаемый подход, вы гарантируете, что предоставляете данные контурного графика для всех комбинаций x,y. - person gcons; 29.07.2017
comment
Я думаю, что вы поменяли местами x и y в своем примере. Широта представляет собой ось Y, поскольку она представляет положение север-юг. Долгота представляет положение восток-запад. - person Gene G.; 30.06.2020
comment
Можно ли сделать эту тепловую карту с доходом и другой переменной? - person stats555; 21.10.2020

Вы можете использовать функцию stat_summary_2d() или stat_summary_hex() для получения аналогичного результата. Эти функции делят данные на ячейки (определяемые x и y), а затем значения z для каждой ячейки суммируются на основе заданной функции. В приведенном ниже примере я выбрал среднее значение в качестве функции агрегирования, и карта в основном показывает среднюю цену в каждой ячейке.

Примечание. Мне нужно было правильно обработать вашу переменную medium_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") 

введите здесь описание изображения

person gcons    schedule 26.07.2017
comment
Спасибо за помощь, но я ищу что-то вроде этого - sromalewski.files.wordpress.com/2011/09/ - person user709413; 26.07.2017