Сглаживание карты ggplot2

Предыдущие сообщения

Очистка карты с помощью geom_tile

Получить границы для состояний в состоянии

Проблема/Вопрос

Я пытаюсь сгладить некоторые данные для сопоставления с ggplot2. Благодаря @MrFlick и @hrbrmstr, я добился большого прогресса, но у меня проблемы с получением эффекта "градиента" над состояниями, которые мне нужны.

Вот пример, чтобы дать вам представление о том, что я ищу:

**** Это именно то, чего я пытаюсь достичь.

http://nrelscience.org/2013/05/30/this-is-how-i-did-it-mapping-in-r-with-ggplot2/

(1) Как я могу использовать ggplot2 с моими данными?

(2) Существует ли лучший способ достижения эффекта градиента?

Цели

Цели, которые я хотел бы получить от этой награды:

(1) Интерполируйте данные для создания растрового объекта, а затем постройте с помощью ggplot2

(или, если больше можно сделать с текущим графиком, а растровый объект не является хорошей стратегией)

(2) Создайте лучшую карту с ggplot2

Текущие результаты

Я играю со многими из этих разных сюжетов, но я до сих пор не доволен результатами по двум причинам: (1) Градиент не говорит столько, сколько я хочу; и (2) Презентация может быть улучшена, хотя я не уверен, как это сделать.

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

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

Наборы данных

Вот два набора данных:

(1) Полный набор данных (175 мб): PRISM_1895_db_all.csv(НЕ ДОСТУПНО)

https://www.dropbox.com/s/uglvwufcr6e9oo6/PRISM_1895_db_all.csv?dl=0

(2) Набор частичных данных (14 мб): PRISM_1895_db.csv(НЕ ДОСТУПНО)

https://www.dropbox.com/s/0evuvrlm49ab9up/PRISM_1895_db.csv?dl=0

*** EDIT: для тех, кого интересуют, наборы данных недоступны, но я сделал сообщение на своем веб-сайте, который соединяет этот код с подмножеством данных Калифорнии в http://johnwoodill.com/pages/r-code.html

Участок 1

PRISM_1895_db <- read.csv("/.../PRISM_1895_db.csv")

regions<- c("north dakota","south dakota","nebraska","kansas","oklahoma","texas","minnesota","iowa","missouri","arkansas", "illinois", "indiana", "wisconsin")

ggplot() + 
  geom_polygon(data=subset(map_data("state"), region %in% regions), aes(x=long, y=lat, group=group)) +
  geom_point(data = PRISM_1895_db, aes(x = longitude, y = latitude, color = APPT), alpha = .5, size = 5) +
  geom_polygon(data=subset(map_data("state"), region %in% regions), aes(x=long, y=lat, group=group), color="white", fill=NA) +
  coord_equal()

enter image description here

Участок 2

PRISM_1895_db < - read.csv( "/.../PRISM_1895_db.csv" )

regions<- c("north dakota","south dakota","nebraska","kansas","oklahoma","texas","minnesota","iowa","missouri","arkansas", "illinois", "indiana", "wisconsin")

ggplot() + 
    geom_polygon(data=subset(map_data("state"), region %in% regions), aes(x=long, y=lat, group=group)) +
    geom_point(data = PRISM_1895_db, aes(x = longitude, y = latitude, color = APPT), alpha = .5, size = 5, shape = 15) +
    geom_polygon(data=subset(map_data("state"), region %in% regions), aes(x=long, y=lat, group=group), color="white", fill=NA) +
    coord_equal()

enter image description here

Участок 3

   PRISM_1895_db <- read.csv("/.../PRISM_1895_db.csv")

    regions<- c("north dakota","south dakota","nebraska","kansas","oklahoma","texas","minnesota","iowa","missouri","arkansas", "illinois", "indiana", "wisconsin")

ggplot() + 
  geom_polygon(data=subset(map_data("state"), region %in% regions), aes(x=long, y=lat, group=group)) +
  stat_summary2d(data=PRISM_1895_db, aes(x = longitude, y = latitude, z = APPT)) +
  geom_polygon(data=subset(map_data("state"), region %in% regions), aes(x=long, y=lat, group=group), color="white", fill=NA)

enter image description here

Ответ 1

пространственный вид CRAN начал меня на "Кригинге". Код ниже занимает 7 минут, чтобы работать на моем ноутбуке. Вы можете попробовать более простые интерполяции (например, какой-то сплайн). Вы также можете удалить некоторые местоположения из регионов с высокой плотностью. Вам не нужны все эти пятна, чтобы получить ту же самую тепловую карту. Насколько я знаю, нет простого способа создать истинный градиент с помощью ggplot2 (gridSVG имеет несколько параметров, но ничего похожего на "градиент сетки", который вы найдете в фантастическом редакторе SVG).

enter image description here

В соответствии с запросом, здесь используется интерполяция с использованием сплайнов (намного быстрее). Еще один код берется из контуры контуров на нерегулярной сетке.

enter image description here

Код для кригинга:

library(data.table)
library(ggplot2)
library(automap)

# Data munging
states=c("AR","IL","MO")
regions=c("arkansas","illinois","missouri")
PRISM_1895_db = as.data.frame(fread("./Downloads/PRISM_1895_db.csv"))
sub_data = PRISM_1895_db[PRISM_1895_db$state %in% states,c("latitude","longitude","APPT")]
coord_vars = c("latitude","longitude")
data_vars = setdiff(colnames(sub_data), coord_vars)
sp_points = SpatialPoints(sub_data[,coord_vars])
sp_df = SpatialPointsDataFrame(sp_points, sub_data[,data_vars,drop=FALSE])

# Create a fine grid
pixels_per_side = 200
bottom.left = apply([email protected],2,min)
top.right = apply([email protected],2,max)
margin = abs((top.right-bottom.left))/10
bottom.left = bottom.left-margin
top.right = top.right+margin
pixel.size = abs(top.right-bottom.left)/pixels_per_side
g = GridTopology(cellcentre.offset=bottom.left,
             cellsize=pixel.size,
             cells.dim=c(pixels_per_side,pixels_per_side))

# Clip the grid to the state regions
map_base_data = subset(map_data("state"), region %in% regions)
colnames(map_base_data)[match(c("long","lat"),colnames(map_base_data))] = c("longitude","latitude")
foo = function(x) {
  state = unique(x$region)
  print(state)
  Polygons(list(Polygon(x[,c("latitude","longitude")])),ID=state)
}
state_pg = SpatialPolygons(dlply(map_base_data, .(region), foo))
grid_points = SpatialPoints(g)
in_points = !is.na(over(grid_points,state_pg))
fit_points = SpatialPoints(as.data.frame(grid_points)[in_points,])

# Do kriging
krig = autoKrige(APPT~1, sp_df, new_data=fit_points)
interp_data = as.data.frame(krig$krige_output)
colnames(interp_data) = c("latitude","longitude","APPT_pred","APPT_var","APPT_stdev")

# Set up map plot
map_base_aesthetics = aes(x=longitude, y=latitude, group=group)
map_base = geom_polygon(data=map_base_data, map_base_aesthetics)
borders = geom_polygon(data=map_base_data, map_base_aesthetics, color="black", fill=NA)

nbin=20
ggplot(data=interp_data, aes(x=longitude, y=latitude)) + 
  geom_tile(aes(fill=APPT_pred),color=NA) +
  stat_contour(aes(z=APPT_pred), bins=nbin, color="#999999") +
  scale_fill_gradient2(low="blue",mid="white",high="red", midpoint=mean(interp_data$APPT_pred)) +
  borders +
  coord_equal() +
  geom_point(data=sub_data,color="black",size=0.3)

Код для интерполяции сплайнов:

library(data.table)
library(ggplot2)
library(automap)
library(plyr)
library(akima)

# Data munging
sub_data = as.data.frame(fread("./Downloads/PRISM_1895_db_all.csv"))
coord_vars = c("latitude","longitude")
data_vars = setdiff(colnames(sub_data), coord_vars)
sp_points = SpatialPoints(sub_data[,coord_vars])
sp_df = SpatialPointsDataFrame(sp_points, sub_data[,data_vars,drop=FALSE])

# Clip the grid to the state regions
regions<- c("north dakota","south dakota","nebraska","kansas","oklahoma","texas",
            "minnesota","iowa","missouri","arkansas", "illinois", "indiana", "wisconsin")
map_base_data = subset(map_data("state"), region %in% regions)
colnames(map_base_data)[match(c("long","lat"),colnames(map_base_data))] = c("longitude","latitude")
foo = function(x) {
  state = unique(x$region)
  print(state)
  Polygons(list(Polygon(x[,c("latitude","longitude")])),ID=state)
}
state_pg = SpatialPolygons(dlply(map_base_data, .(region), foo))

# Set up map plot
map_base_aesthetics = aes(x=longitude, y=latitude, group=group)
map_base = geom_polygon(data=map_base_data, map_base_aesthetics)
borders = geom_polygon(data=map_base_data, map_base_aesthetics, color="black", fill=NA)

# Do spline interpolation with the akima package
fld = with(sub_data, interp(x = longitude, y = latitude, z = APPT, duplicate="median",
                            xo=seq(min(map_base_data$longitude), max(map_base_data$longitude), length = 100),
                            yo=seq(min(map_base_data$latitude), max(map_base_data$latitude), length = 100),
                            extrap=TRUE, linear=FALSE))
melt_x = rep(fld$x, times=length(fld$y))
melt_y = rep(fld$y, each=length(fld$x))
melt_z = as.vector(fld$z)
level_data = data.frame(longitude=melt_x, latitude=melt_y, APPT=melt_z)
interp_data = na.omit(level_data)
grid_points = SpatialPoints(interp_data[,2:1])
in_points = !is.na(over(grid_points,state_pg))
inside_points = interp_data[in_points, ]

ggplot(data=inside_points, aes(x=longitude, y=latitude)) + 
  geom_tile(aes(fill=APPT)) + 
  stat_contour(aes(z=APPT)) +
  coord_equal() + 
  scale_fill_gradient2(low="blue",mid="white",high="red", midpoint=mean(inside_points$APPT)) +
  borders

Ответ 2

Предыдущий ответ был не оптимальным (или точным) для ваших нужд. Это немного взломать:

gg <- ggplot() 
gg <- gg + geom_polygon(data=subset(map_data("state"), region %in% regions), 
                        aes(x=long, y=lat, group=group))
gg <- gg + geom_point(data=PRISM_1895_db, aes(x=longitude, y=latitude, color=APPT), 
                      size=5, alpha=1/15, shape=19)
gg <- gg + scale_color_gradient(low="#023858", high="#ece7f2")
gg <- gg + geom_polygon(data=subset(map_data("state"), region %in% regions), 
                        aes(x=long, y=lat, group=group), color="white", fill=NA)
gg <- gg + coord_equal()
gg

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

enter image description here

Другим вариантом будет интерполировать больше значений APPT между долготой и широтами, которые у вас есть, а затем преобразовать их в более плотный растровый объект и построить его с помощью geom_raster, как в приведенном примере.