Построение SpatRaster с помощью ggmap в R

Благодаря этому посту я смог вычислить некоторые 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% и накладывает их друг на друга на графике. Однако я не могу заставить этот первый шаг работать. Все данные для репликации моего кода находятся здесь.

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

mikejwilliamson 27.05.2024 15:59
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
1
52
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Чтобы это заработало, необходимо внести несколько изменений в исходный ответ на вопрос. В первую очередь это связано с собственной 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())

Другие вопросы по теме