rOpenSpain / climaemet

R Climate AEMET Tools
https://ropenspain.github.io/climaemet/
GNU General Public License v3.0
41 stars 2 forks source link

How to extend climaemet? Use case for /api/prediccion/especifica/playa/{playa} #54

Closed dieghernan closed 4 months ago

dieghernan commented 4 months ago

Full example on how to use climaemet to access other API endpoints provided by AEMET but not implemented yet. Use case for api endpoint /api/prediccion/especifica/playa/{playa}. See also Extending climaemet article.

We need the following:

Full reprex

# La API funciona con llamadas individuales a playas. Necesitamos primero la
# BBDD de playas correspondiente
library(tidyverse)
library(climaemet)
library(sf)
library(mapSpain)

# Tratamiento BBDD playas ----
playas <- read_csv2("https://www.aemet.es/documentos/es/eltiempo/prediccion/playas/Playas_codigos.csv")
#> ℹ Using "','" as decimal and "'.'" as grouping mark. Use `read_delim()` for more control.
#> Rows: 591 Columns: 8
#> ── Column specification ────────────────────────────────────────────────────────
#> Delimiter: ";"
#> chr (8): ID_PLAYA, NOMBRE_PLAYA, ID_PROVINCIA, NOMBRE_PROVINCIA, ID_MUNICIPI...
#> 
#> ℹ Use `spec()` to retrieve the full column specification for this data.
#> ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.

playas
#> # A tibble: 591 × 8
#>    ID_PLAYA NOMBRE_PLAYA              ID_PROVINCIA NOMBRE_PROVINCIA ID_MUNICIPIO
#>    <chr>    <chr>                     <chr>        <chr>            <chr>       
#>  1 0301101  Raco de l'Albir           03           Alacant/Alicante 03011       
#>  2 0301401  Sant Joan / San Juan      03           Alacant/Alicante 03014       
#>  3 0301408  El Postiguet              03           Alacant/Alicante 03014       
#>  4 0301410  Saladar                   03           Alacant/Alicante 03014       
#>  5 0301808  La Roda                   03           Alacant/Alicante 03018       
#>  6 0301809  Cap Blanch                03           Alacant/Alicante 03018       
#>  7 0303102  Llevant / Playa de Levan… 03           Alacant/Alicante 03031       
#>  8 0303104  Ponent / Playa de Ponien… 03           Alacant/Alicante 03031       
#>  9 0304105  Cala Fustera              03           Alacant/Alicante 03041       
#> 10 0304704  La Fossa                  03           Alacant/Alicante 03047       
#> # ℹ 581 more rows
#> # ℹ 3 more variables: NOMBRE_MUNICIPIO <chr>, LATITUD <chr>, LONGITUD <chr>

# Vamos a convertir latitud y longitud a grados decimales para poder trabajar
# con objetos espaciales

# Segun https://www.latlong.net/degrees-minutes-seconds-to-decimal-degrees
# creamos funcion auxiliar
degrees2dec <- function(x) {
  # Miramos signo
  minus <- ifelse(str_detect(x, "^-"), -1, 1)

  # Partimos en grados, minutos y segundos (3 partes) y nos quedamos con
  # los datos como doubles
  pieces <- str_split(x, " ", simplify = TRUE) %>%
    str_remove_all("[^0-9]") %>%
    as.double()

  # Convertimos las pieces con el signo
  dec <- minus * sum(pieces / c(1, 60, 60^2))

  dec
}

playas_sf <- playas %>%
  mutate(
    lat = map_dbl(LATITUD, degrees2dec),
    lon = map_dbl(LONGITUD, degrees2dec)
  ) %>%
  # Convertimos a sf
  st_as_sf(coords = c("lon", "lat"), crs = st_crs(4326))

# Comprobamos en mapa

esp <- esp_get_country(moveCAN = FALSE)

ggplot(esp) +
  geom_sf() +
  geom_sf(data = playas_sf) +
  ggtitle("Check playas como objeto sf")


# OK

## Extracción via API ----

# Necesitaremos un wrapper y una función de extraccion de resultados

# Funcion extraccion:
extrae_playas_output <- function(pred) {
  cols <- names(pred$prediccion$dia[[1]])

  outp <- unnest(pred$prediccion$dia[[1]],
    cols = all_of(cols),
    names_sep = "_"
  ) %>%
    bind_cols(pred %>% select(elaborado, nombre, localidad)) %>%
    relocate(elaborado, nombre, localidad, fecha) %>%
    # Trata fechas
    mutate(
      elaborado = as_datetime(elaborado),
      fecha = as.Date(as.character(fecha), format = "%Y%m%d")
    )

  outp
}

# Completamos la API con un wrapper

aemet_playa_single <- function(id_playa) {
  api_entry <- "/api/prediccion/especifica/playa/"

  api_call <- paste0(api_entry, id_playa)

  pred <- get_data_aemet(api_call)
  out <- extrae_playas_output(pred)

  lastdf <- out %>%
    mutate(ID_PLAYA = id_playa) %>%
    relocate(ID_PLAYA)

  lastdf
}

# Uso del wrapper -----

allids <- pull(playas, ID_PLAYA)

# Ejemplo: extrayendo una playa
single_example <- aemet_playa_single(allids[1])

single_example
#> # A tibble: 3 × 36
#>   ID_PLAYA elaborado           nombre     localidad fecha      estadoCielo_value
#>   <chr>    <dttm>              <chr>          <int> <date>     <chr>            
#> 1 0301101  2024-06-20 04:50:21 Raco de l…      3011 2024-06-20 ""               
#> 2 0301101  2024-06-20 04:50:21 Raco de l…      3011 2024-06-21 ""               
#> 3 0301101  2024-06-20 04:50:21 Raco de l…      3011 2024-06-22 ""               
#> # ℹ 30 more variables: estadoCielo_f1 <int>, estadoCielo_descripcion1 <chr>,
#> #   estadoCielo_f2 <int>, estadoCielo_descripcion2 <chr>, viento_value <chr>,
#> #   viento_f1 <int>, viento_descripcion1 <chr>, viento_f2 <int>,
#> #   viento_descripcion2 <chr>, oleaje_value <chr>, oleaje_f1 <int>,
#> #   oleaje_descripcion1 <chr>, oleaje_f2 <int>, oleaje_descripcion2 <chr>,
#> #   tMaxima_value <chr>, tMaxima_valor1 <int>, sTermica_value <chr>,
#> #   sTermica_valor1 <int>, sTermica_descripcion1 <chr>, tAgua_value <chr>, …

# Ejemplo, extrayendo 3 playas (en loop o apply)
several_examples <- map(allids[1:3], aemet_playa_single) %>%
  list_rbind()

several_examples
#> # A tibble: 9 × 36
#>   ID_PLAYA elaborado           nombre     localidad fecha      estadoCielo_value
#>   <chr>    <dttm>              <chr>          <int> <date>     <chr>            
#> 1 0301101  2024-06-20 04:50:21 Raco de l…      3011 2024-06-20 ""               
#> 2 0301101  2024-06-20 04:50:21 Raco de l…      3011 2024-06-21 ""               
#> 3 0301101  2024-06-20 04:50:21 Raco de l…      3011 2024-06-22 ""               
#> 4 0301401  2024-06-20 04:50:21 Sant Joan…      3014 2024-06-20 ""               
#> 5 0301401  2024-06-20 04:50:21 Sant Joan…      3014 2024-06-21 ""               
#> 6 0301401  2024-06-20 04:50:21 Sant Joan…      3014 2024-06-22 ""               
#> 7 0301408  2024-06-20 04:50:21 El Postig…      3014 2024-06-20 ""               
#> 8 0301408  2024-06-20 04:50:21 El Postig…      3014 2024-06-21 ""               
#> 9 0301408  2024-06-20 04:50:21 El Postig…      3014 2024-06-22 ""               
#> # ℹ 30 more variables: estadoCielo_f1 <int>, estadoCielo_descripcion1 <chr>,
#> #   estadoCielo_f2 <int>, estadoCielo_descripcion2 <chr>, viento_value <chr>,
#> #   viento_f1 <int>, viento_descripcion1 <chr>, viento_f2 <int>,
#> #   viento_descripcion2 <chr>, oleaje_value <chr>, oleaje_f1 <int>,
#> #   oleaje_descripcion1 <chr>, oleaje_f2 <int>, oleaje_descripcion2 <chr>,
#> #   tMaxima_value <chr>, tMaxima_valor1 <int>, sTermica_value <chr>,
#> #   sTermica_valor1 <int>, sTermica_descripcion1 <chr>, tAgua_value <chr>, …

# Ejemplo añadiendo localización
playas_pred <- playas_sf %>%
  select(ID_PLAYA) %>%
  inner_join(several_examples)
#> Joining with `by = join_by(ID_PLAYA)`

ggplot(playas_pred) +
  geom_sf(aes(col = viento_descripcion2)) +
  facet_wrap(~fecha)

Created on 2024-06-20 with reprex v2.1.0

Session info ``` r sessioninfo::session_info() #> ─ Session info ─────────────────────────────────────────────────────────────── #> setting value #> version R version 4.4.0 (2024-04-24) #> os Ubuntu 20.04.6 LTS #> system x86_64, linux-gnu #> ui X11 #> language (EN) #> collate C.UTF-8 #> ctype C.UTF-8 #> tz UTC #> date 2024-06-20 #> pandoc 3.1.1 @ /usr/lib/rstudio-server/bin/quarto/bin/tools/ (via rmarkdown) #> #> ─ Packages ─────────────────────────────────────────────────────────────────── #> package * version date (UTC) lib source #> bit 4.0.5 2022-11-15 [1] RSPM (R 4.4.0) #> bit64 4.0.5 2020-08-30 [1] RSPM (R 4.4.0) #> class 7.3-22 2023-05-03 [2] CRAN (R 4.4.0) #> classInt 0.4-10 2023-09-05 [1] RSPM (R 4.4.0) #> cli 3.6.2 2023-12-11 [1] RSPM (R 4.4.0) #> climaemet * 1.2.1 2024-01-30 [1] RSPM (R 4.4.0) #> colorspace 2.1-0 2023-01-23 [1] RSPM (R 4.4.0) #> crayon 1.5.2 2022-09-29 [1] RSPM (R 4.4.0) #> curl 5.2.1 2024-03-01 [1] RSPM (R 4.4.0) #> DBI 1.2.3 2024-06-02 [1] RSPM (R 4.4.0) #> digest 0.6.35 2024-03-11 [1] RSPM (R 4.4.0) #> dplyr * 1.1.4 2023-11-17 [1] RSPM (R 4.4.0) #> e1071 1.7-14 2023-12-06 [1] RSPM (R 4.4.0) #> evaluate 0.24.0 2024-06-10 [1] RSPM (R 4.4.0) #> fansi 1.0.6 2023-12-08 [1] RSPM (R 4.4.0) #> farver 2.1.2 2024-05-13 [1] RSPM (R 4.4.0) #> fastmap 1.2.0 2024-05-15 [1] RSPM (R 4.4.0) #> forcats * 1.0.0 2023-01-29 [1] RSPM (R 4.4.0) #> fs 1.6.4 2024-04-25 [1] RSPM (R 4.4.0) #> generics 0.1.3 2022-07-05 [1] RSPM (R 4.4.0) #> ggplot2 * 3.5.1 2024-04-23 [1] RSPM (R 4.4.0) #> glue 1.7.0 2024-01-09 [1] RSPM (R 4.4.0) #> gtable 0.3.5 2024-04-22 [1] RSPM (R 4.4.0) #> highr 0.11 2024-05-26 [1] RSPM (R 4.4.0) #> hms 1.1.3 2023-03-21 [1] RSPM (R 4.4.0) #> htmltools 0.5.8.1 2024-04-04 [1] RSPM (R 4.4.0) #> httr 1.4.7 2023-08-15 [1] RSPM (R 4.4.0) #> jsonlite 1.8.8 2023-12-04 [1] RSPM (R 4.4.0) #> KernSmooth 2.23-22 2023-07-10 [2] CRAN (R 4.4.0) #> knitr 1.47 2024-05-29 [1] RSPM (R 4.4.0) #> lifecycle 1.0.4 2023-11-07 [1] RSPM (R 4.4.0) #> lubridate * 1.9.3 2023-09-27 [1] RSPM (R 4.4.0) #> magrittr 2.0.3 2022-03-30 [1] RSPM (R 4.4.0) #> mapSpain * 0.9.1 2024-06-10 [1] RSPM (R 4.4.0) #> munsell 0.5.1 2024-04-01 [1] RSPM (R 4.4.0) #> pillar 1.9.0 2023-03-22 [1] RSPM (R 4.4.0) #> pkgconfig 2.0.3 2019-09-22 [1] RSPM (R 4.4.0) #> proxy 0.4-27 2022-06-09 [1] RSPM (R 4.4.0) #> purrr * 1.0.2 2023-08-10 [1] RSPM (R 4.4.0) #> R.cache 0.16.0 2022-07-21 [1] RSPM (R 4.4.0) #> R.methodsS3 1.8.2 2022-06-13 [1] RSPM (R 4.4.0) #> R.oo 1.26.0 2024-01-24 [1] RSPM (R 4.4.0) #> R.utils 2.12.3 2023-11-18 [1] RSPM (R 4.4.0) #> R6 2.5.1 2021-08-19 [1] RSPM (R 4.4.0) #> Rcpp 1.0.12 2024-01-09 [1] RSPM (R 4.4.0) #> readr * 2.1.5 2024-01-10 [1] RSPM (R 4.4.0) #> reprex 2.1.0 2024-01-11 [1] RSPM (R 4.4.0) #> rlang 1.1.4 2024-06-04 [1] RSPM (R 4.4.0) #> rmarkdown 2.27 2024-05-17 [1] RSPM (R 4.4.0) #> rstudioapi 0.16.0 2024-03-24 [1] RSPM (R 4.4.0) #> scales 1.3.0 2023-11-28 [1] RSPM (R 4.4.0) #> sessioninfo 1.2.2 2021-12-06 [1] RSPM (R 4.4.0) #> sf * 1.0-16 2024-03-24 [1] RSPM (R 4.4.0) #> stringi 1.8.4 2024-05-06 [1] RSPM (R 4.4.0) #> stringr * 1.5.1 2023-11-14 [1] RSPM (R 4.4.0) #> styler 1.10.3 2024-04-07 [1] RSPM (R 4.4.0) #> tibble * 3.2.1 2023-03-20 [1] RSPM (R 4.4.0) #> tidyr * 1.3.1 2024-01-24 [1] RSPM (R 4.4.0) #> tidyselect 1.2.1 2024-03-11 [1] RSPM (R 4.4.0) #> tidyverse * 2.0.0 2023-02-22 [1] RSPM (R 4.4.0) #> timechange 0.3.0 2024-01-18 [1] RSPM (R 4.4.0) #> tzdb 0.4.0 2023-05-12 [1] RSPM (R 4.4.0) #> units 0.8-5 2023-11-28 [1] RSPM (R 4.4.0) #> utf8 1.2.4 2023-10-22 [1] RSPM (R 4.4.0) #> vctrs 0.6.5 2023-12-01 [1] RSPM (R 4.4.0) #> vroom 1.6.5 2023-12-05 [1] RSPM (R 4.4.0) #> withr 3.0.0 2024-01-16 [1] RSPM (R 4.4.0) #> xfun 0.45 2024-06-16 [1] RSPM (R 4.4.0) #> xml2 1.3.6 2023-12-04 [1] RSPM (R 4.4.0) #> yaml 2.3.8 2023-12-11 [1] RSPM (R 4.4.0) #> #> [1] /cloud/lib/x86_64-pc-linux-gnu-library/4.4 #> [2] /opt/R/4.4.0/lib/R/library #> #> ────────────────────────────────────────────────────────────────────────────── ```