Благодаря этому посту я смог вычислить некоторые KUD, замаскированные по области шейп-файла, а затем построить их с помощью ggplot и SpatRaster из пакета terra.
Однако я хотел бы сопоставить это с ggmap. Мой текущий код приведен ниже.
# Create sf object from shapefile, project to WGS84 UTM zone 31N/EPSG:32631
Abberton_utm <- st_read("WFD_Lake_Water_Bodies_Cycle_2.shp") %>%
st_as_sf() %>%
st_transform(32631)
#filter data to remove inaccurate positions
AB_filt <- AB_DAT %>%
dplyr::filter(HPE <= 2)
#code for plotting KUD data
AB_KUD <- AB_filt %>%
dplyr::arrange(Transmitter, DateTime) %>%
#dplyr::filter(week == "24") %>%
dplyr::select(Species, X_UTM, Y_UTM)
coordinates(AB_KUD) <- c("X_UTM","Y_UTM")
crs(AB_KUD) <- "EPSG:32631"
# Create estUDm object
kud <- kernelUD(AB_KUD[,1], h = "href") # href = the reference bandwidth
# Create SpatRaster template for rasterize()
# Only need to do this once, no need to replicate it inside your loop
r <- rast(ext(Abberton_utm), ncol = 100, nrow = 100, crs = "EPSG:32631")
# Create 95th pecentile polygon sf from kud for initial ggplot()
sf_poly <- getverticeshr(kud, percent = 95) %>%
st_as_sf() %>%
st_set_crs(32631)
# Convert sf_poly to SpatRaster, crop and mask to Abberton_utm
tmpr <- terra::rasterize(sf_poly, r) %>%
crop(., Abberton_utm, mask = TRUE)
# Assign percentile value to cells in tmpr
tmpr[] <- ifelse(is.na(tmpr[]), NA, 95)
# Create initial plot
p <- ggplot() +
geom_spatraster(data = tmpr, show.legend = FALSE)
Это просто вычисляет 95% KUD и использует ggplot для его отображения. Однако я хочу построить график на основе ggmap с помощью приведенного ниже кода.
# Your code for obtaining the map
Abberton_eastern <- c(0.875, 51.827)
AbRes <- get_map(location=Abberton_eastern, source = "google", maptype='stamen_terrain', zoom=14)
Впоследствии я использую цикл, который вычисляет KUD с интервалом 5% и накладывает их друг на друга на графике. Однако я не могу заставить этот первый шаг работать. Все данные для репликации моего кода находятся здесь.





Чтобы это заработало, необходимо внести несколько изменений в исходный ответ на вопрос. В первую очередь это связано с собственной CRS, которую Google присваивает своим данным. Если бы вы проецировали данные Google, они выглядели бы искаженными, особенно текстовые метки. Чтобы учесть это, все остальные данные будут совпадать с данными Google, например. WGS84/EPSG: 4326.
Я позволил себе некоторые вольности с указанными вами параметрами, чтобы создать, возможно, более сбалансированную карту, например. включено все водохранилище Аббертон. Если это нежелательно или у вас возникли проблемы с адаптацией, прокомментируйте, и я обновлю ответ.
library(sf)
library(adehabitatHR)
library(raster)
library(viridis)
library(dplyr)
library(terra)
library(tidyterra)
library(ggmap)
library(ggplot2)
# Register Google API key
register_google(key = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX")
# Set sf EPSG CRS value native to map source e.g. ggmap == 4326
mapcrs <- 4326
# Set SpatRaster CRS
mapcrsr <- "EPSG:4326"
# Create sf object from shapefile
Abberton <- st_read("WFD_Lake_Water_Bodies_Cycle_2.shp") %>%
st_as_sf() %>%
st_transform(mapcrs)
# Create sf point object, set data crs, project to mapcrs, convert to sp
AB_KUD <- read.csv("AB_KUD.csv") %>%
st_as_sf(coords = c("X_UTM","Y_UTM"), crs = 32631) %>%
st_transform(mapcrs) %>%
as_Spatial()
# Create estUDm object
kud <- kernelUD(AB_KUD[,1], h = "href") # href = the reference bandwidth
# Create SpatRaster template for rasterize()
r <- rast(ext(Abberton), ncol = 100, nrow = 100, crs = mapcrsr)
# Function to get polygon from bounding box (basis for plot extent and Google map)
bbox_poly <- function(x) {
bb <- sf::st_bbox(x)
p <- matrix(
c(bb["xmin"], bb["ymin"],
bb["xmin"], bb["ymax"],
bb["xmax"], bb["ymax"],
bb["xmax"], bb["ymin"],
bb["xmin"], bb["ymin"]),
ncol = 2, byrow = T
)
sf::st_polygon(list(p))
}
# Create box sf
box <- st_sfc(bbox_poly(Abberton)) %>%
st_set_crs(mapcrs)
# Return st_bbox() coordinates for plot extent
mapext <- st_bbox(box)
# Get box centroid for get_googlemap() centre
st_coordinates(st_centroid(box))
# X Y
# [1,] 0.8564451 51.82594
# Define map centre
Abberton_eastern <- c(lon = 0.8564451, lat = 51.82594)
# Get map from Google API
tmp <- get_googlemap(center = Abberton_eastern, # US spelling only!
source = "google",
maptype = "terrain",
scale = 2,
zoom = 13,
style = "feature:poi|visibility:off") # Remove all POI pins
# Convert Google map object to SpatRaster
AbRes <- rast(tmp)
# Write rast() to working directory
writeRaster(AbRes, "AbRes_z13_scale2.tif", overwrite = TRUE)
# Create initial plot
p <- ggplot() +
geom_spatraster_rgb(data = AbRes)
# Loop percentile vector and add to p
for(x in seq(95, 10, -5)){
# Convert kud to polygon sf for the current percentile
sf_poly <- getverticeshr(kud, percent = x) %>%
st_as_sf() %>%
st_set_crs(mapcrs)
# Convert sf_poly to SpatRaster, crop and mask to Abberton_utm
tmpr <- terra::rasterize(sf_poly, r) %>%
crop(., Abberton, mask = TRUE)
# Assign percentile value to cells in tmpr
tmpr[] <- ifelse(is.na(tmpr[]), NA, x)
# Add tmpr to ggplot()
p <- p +
geom_spatraster(data = tmpr, show.legend = FALSE)
}
# Set plot extent offset in map units
extoff <- 0.005
# Plot p
p +
# geom_sf(data = Abberton, fill = NA, colour = alpha("black", alpha = 0.7)) +
scale_fill_gradientn(colours = viridis(100)[seq(95, 10, -5)],
na.value = "transparent") +
coord_sf(expand = FALSE,
xlim = c(mapext[[1]] - extoff, mapext[[3]] + extoff),
ylim = c(mapext[[2]] - extoff, mapext[[4]] + extoff)) +
theme(legend.position = "none",
panel.background = element_blank())
Немного застрял @LTyrone. Я думаю, что если я смогу проработать этот первый шаг, добавить его в цикл будет достаточно просто.