Лучший метод пространственной интерполяции для географических тепловых / контурных карт? - PullRequest
0 голосов
/ 25 мая 2018

Я хотел бы использовать что-то вроде ggplot2 и ggmap до , чтобы получить тепловую карту произвольных значений , таких как цены на квадратный метр по географическому району на уровне улицы(с высоким разрешением) .

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

Для этого я использовал библиотеки akima (двумерная интерполяция с сеткой для нерегулярных данных) и mgcv (обобщенные аддитивные модели с интегрированной оценкой гладкости), однако мои знания методов интерполяции в лучшем случае посредственны ирезультаты, которые я смог получить, недостаточно удовлетворительны.

Рассмотрим следующий пример:

Данные

library(ggplot2)
library(ggmap)

## data simulation
set.seed(1945)

df <- tibble(x = rnorm(500, -0.7406, 0.03),
             y = rnorm(500, 51.9976, 0.03),
             z = abs(rnorm(500, 2000, 1000)))

Карта, диаграмма рассеяния, график плотности

## ggmap
map <- get_map("Bletchley Park, Bletchley, Milton Keynes", zoom = 13, source = "stamen", maptype = "toner-background")
q <- ggmap(map, extent = "device", darken = .5)

## scatterplot over map
q + geom_point(aes(x, y), data = df, colour = z)

## classic density heat map
q + 
  stat_density2d(aes(x=x, y=y, fill=..level..), data=df, geom="polygon", alpha = .2) + 
  geom_density_2d(aes(x=x, y=y), data=df, colour = "white", alpha = .4) +
  scale_fill_distiller(palette = "Spectral")

Как видите, данные довольно плотны по выбранной области, и карта плотности плотности отлично смотрится с закругленными краями иd замкнутые кривые (за исключением некоторых внешних слоев).

density plot

Интерполяция и построение графиков с использованием akima

## akima interpolation
library(akima)

df_akima <-interp2xyz(interp(x=df$x, y=df$y, z=df$z, duplicate="mean", linear = T,
                             xo=seq(min(df$x), max(df$x), length=200),
                             yo=seq(min(df$y), max(df$y), length=200)), data.frame=TRUE)

## akima plot
q +
  geom_tile(aes(x = x, y = y, fill = z), data = df_akima, alpha = .4) +
  stat_contour(aes(x = x, y = y, z = z, fill = ..level..), data = df_akima, geom = 'polygon', alpha = .4) +
  geom_contour(aes(x = x, y = y, z = z), data = df_akima, colour = 'white', alpha = .4) +
  scale_fill_distiller(palette = "Spectral", na.value = NA)

Это приводит кплотная сетка интерполированных значений (для обеспечения достаточного разрешения), и в то время как нижний график является приемлемым, контурные графики слишком рваные, и многие кривые не закрыты.

linear akima

Нелинейная интерполяция с использованием linear = F является более плавной, но, по-видимому, жертвует разрешением и сходит с ума с числами (отрицательные значения z).

non-linear akima

Интерполяция и построение графиков с использованием mgcv

## mgcv interpolation
library(mgcv)

gam <- gam(z ~ s(x, y, bs = 'sos'), data = df)
df_mgcv <- data.frame(expand.grid(x = seq(min(df$x), max(df$x), length=200),
                                  y = seq(min(df$y), max(df$y), length=200)))
resp <- predict(gam, df_mgcv, type = "response")
df_mgcv$z <- resp

## mgcv plot
q +
  geom_tile(aes(x = x, y = y, fill = z), data = df_mgcv, alpha = .4) +
  stat_contour(aes(x = x, y = y, z = z, fill = ..level..), data = df_mgcv, geom = 'polygon', alpha = .4) +
  geom_contour(aes(x = x, y = y, z = z), data = df_mgcv, colour = 'white', alpha = .4) +
  scale_fill_distiller(palette = "Spectral", na.value = NA)

Тот же процесс с использованием mgcv приводит к красивому и плавному графику, но разрешение намного ниже, и практически все кривые не закрыты.

mgcv

Вопросы

  1. Не могли бы вы предложить лучший метод или изменить мою попытку получить график, похожий на первый (чистые, соединенные и плавные линии с высоким разрешением)?

  2. Можно ли закрытькривые, например, на последнем графике (заштрихованная область должна быть рассчитана за пределами границ изображения)?

Спасибо за потраченное время!

Ответы [ 2 ]

0 голосов
/ 27 мая 2018

Проблема с вашими картами не в методе интерполяции, который вы используете, а в том, как ggplot отображает линии плотности.Вот ответ на этот вопрос: Удалите пробелы в диаграмме ggplot stat_density2d без изменения пределов XY .

Линии плотности выходят за пределы карты, поэтому любой многоугольник, выходящий за пределы области графика, отображается неправильно(ggplot закроет многоугольник, используя следующую точку соответствующего уровня).Это не очень заметно на вашей первой карте, потому что разрешение интерполяции низкое.

Хитрость, предложенная Эндрю , заключается в том, чтобы сначала расширить область графика, чтобы линии плотности отображались правильно, а затем отрежьте область отображения, чтобы скрыть дополнительное пространство.Поскольку я проверил его решение на вашем первом примере, вот код:

q + 
  stat_density2d(
    aes(x = x, y = y, fill = ..level..),
    data = df,
    geom = "polygon",
    alpha = .2,
    color = "white",
    bins = 20
  ) + 
  scale_fill_distiller(
    palette = "Spectral"
  ) +
  xlim(
    min(df$x) - 10^-5,
    max(df$x) + 10^-5
  ) +
  ylim(
    min(df$y) - 10^-3,
    max(df$y) + 10^-3
  ) +
  coord_equal(
    expand = FALSE,
    xlim = c(-.778, -.688),
    ylim = c(51.965, 52.03)
  )

Единственное отличие состоит в том, что я использовал min()- / max() + вместо фиксированных чисел и coord_equal, чтобы карта не была искажена.Кроме того, я вручную указал большее количество уровней (используя bin), поскольку при увеличении площади графика stat_density автоматически выбирает более низкое разрешение.

Что касается лучшего метода интерполяции, это зависит от вашей цели.и тип данных у вас есть.Вопрос не в том, какой метод лучше подходит для вашей карты, а в том, какой метод лучше подходит для ваших данных.Это очень широкая проблема, выходящая за рамки этого пространства.Но вот хорошее руководство: http://www.rspatial.org/analysis/rst/4-interpolation.html

Для общих идей о том, как сделать хорошие карты в R, используя ggplot: http://spatial.ly/r/

0 голосов
/ 26 мая 2018

Извините, я не могу сейчас запустить ваш пример, чтобы предоставить подробности.Но попробуйте autoKrige () из пакета automap.

Кригинг - отличный метод для интерполяции.Просто убедитесь, что ваши данные соответствуют заявкам.Вот хорошее руководство: https://gisgeography.com/kriging-interpolation-prediction/

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...