Skip to content

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

@dieghernan

Description

@dieghernan

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:

  • Data base with ids of playas (as there are no batching, we would need to perform queries individually for each beach).
  • API wrapper with the call using climaemet and
  • Helper function to handle the output of the API, as it is a bit messy.

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
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
#> 
#> ──────────────────────────────────────────────────────────────────────────────

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions