diff --git a/.github/workflows/check-examples.yaml b/.github/workflows/check-examples.yaml index 0f450201..95b0fc75 100644 --- a/.github/workflows/check-examples.yaml +++ b/.github/workflows/check-examples.yaml @@ -6,7 +6,8 @@ on: pull_request: branches: [main, master] schedule: - - cron: '0 16 * * 1,6' + - cron: '27 17 * * 1,5' + workflow_dispatch: name: R-CMD-check-examples @@ -26,6 +27,7 @@ jobs: env: GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }} AEMET_API_KEY: ${{ secrets.AEMET_API_KEY }} + AEMET_API_KEY01: ${{ secrets.AEMET_API_KEY_PKGDOWN }} R_KEEP_PKG_SOURCE: yes steps: diff --git a/.github/workflows/rostemplate-gh-pages.yaml b/.github/workflows/rostemplate-gh-pages.yaml index c6bc36f2..93ec2f9e 100644 --- a/.github/workflows/rostemplate-gh-pages.yaml +++ b/.github/workflows/rostemplate-gh-pages.yaml @@ -15,7 +15,7 @@ jobs: runs-on: windows-latest env: GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }} - AEMET_API_KEY: ${{ secrets.AEMET_API_KEY }} + AEMET_API_KEY: ${{ secrets.AEMET_API_KEY_PKGDOWN }} steps: - uses: actions/checkout@v4 diff --git a/.github/workflows/test-coverage.yaml b/.github/workflows/test-coverage.yaml new file mode 100644 index 00000000..53704a08 --- /dev/null +++ b/.github/workflows/test-coverage.yaml @@ -0,0 +1,58 @@ +# Workflow derived from https://github.com/r-lib/actions/tree/v2/examples +# Need help debugging build failures? Start at https://github.com/r-lib/actions#where-to-find-help +on: + push: + branches: [main, master] + pull_request: + branches: [main, master] + +name: test-coverage + +jobs: + test-coverage: + runs-on: windows-latest + env: + GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }} + CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} + AEMET_API_KEY: ${{ secrets.AEMET_API_KEY_CODECOV }} + AEMET_API_KEY01: ${{ secrets.AEMET_API_KEY }} + AEMET_API_KEY02: ${{ secrets.AEMET_API_KEY_PKGDOWN }} + + + steps: + - uses: actions/checkout@v4 + + - uses: r-lib/actions/setup-r@v2 + with: + use-public-rspm: true + + - uses: r-lib/actions/setup-r-dependencies@v2 + with: + extra-packages: any::covr + needs: coverage + + - name: Test coverage + run: | + token <- Sys.getenv("CODECOV_TOKEN", "") + covr::codecov( + quiet = FALSE, + clean = FALSE, + install_path = file.path(normalizePath(Sys.getenv("RUNNER_TEMP"), winslash = "/"), "package"), + token = if (token != "") token + ) + shell: Rscript {0} + + - name: Show testthat output + if: always() + run: | + ## -------------------------------------------------------------------- + find '${{ runner.temp }}/package' -name 'testthat.Rout*' -exec cat '{}' \; || true + shell: bash + + - name: Upload test results + if: failure() + uses: actions/upload-artifact@v4 + with: + name: coverage-test-failures + path: ${{ runner.temp }}/package + diff --git a/.github/workflows/update-docs.yaml b/.github/workflows/update-docs.yaml index 15bc52a8..64e03433 100644 --- a/.github/workflows/update-docs.yaml +++ b/.github/workflows/update-docs.yaml @@ -9,6 +9,7 @@ jobs: env: GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }} AEMET_API_KEY: ${{ secrets.AEMET_API_KEY }} + AEMET_API_KEY01: ${{ secrets.AEMET_API_KEY_PKGDOWN }} steps: - uses: actions/checkout@v4 diff --git a/CITATION.cff b/CITATION.cff index 7c914d45..661cac01 100644 --- a/CITATION.cff +++ b/CITATION.cff @@ -91,6 +91,18 @@ references: address: Vienna, Austria year: '2024' version: '>= 3.6.0' +- type: software + title: cli + abstract: 'cli: Helpers for Developing Command Line Interfaces' + notes: Imports + url: https://cli.r-lib.org + repository: https://CRAN.R-project.org/package=cli + authors: + - family-names: Csárdi + given-names: Gábor + email: csardi.gabor@gmail.com + year: '2024' + version: '>= 3.0.0' - type: software title: dplyr abstract: 'dplyr: A Grammar of Data Manipulation' @@ -180,9 +192,6 @@ references: email: jeroen@berkeley.edu orcid: https://orcid.org/0000-0002-4035-0289 year: '2024' - identifiers: - - type: url - value: https://arxiv.org/abs/1403.2805 version: '>= 1.7.0' - type: software title: rappdirs @@ -421,4 +430,16 @@ references: orcid: https://orcid.org/0000-0001-8049-7069 year: '2024' version: '>= 0.9.0' +- type: software + title: testthat + abstract: 'testthat: Unit Testing for R' + notes: Suggests + url: https://testthat.r-lib.org + repository: https://CRAN.R-project.org/package=testthat + authors: + - family-names: Wickham + given-names: Hadley + email: hadley@posit.co + year: '2024' + version: '>= 3.0.0' diff --git a/DESCRIPTION b/DESCRIPTION index b1bc444f..f8ae1ca7 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -21,6 +21,7 @@ BugReports: https://github.com/rOpenSpain/climaemet/issues Depends: R (>= 3.6.0) Imports: + cli (>= 3.0.0), dplyr (>= 1.0.0), ggplot2 (>= 3.3.2), httr2 (>= 1.0.0), @@ -39,12 +40,15 @@ Suggests: lubridate, rmarkdown, scales, - sf (>= 0.9.0) + sf (>= 0.9.0), + testthat (>= 3.0.0) VignetteBuilder: knitr Config/Needs/website: mapSpain, classInt, terra, sf, gstat, geoR, tidyverse, tidyterra, scales, gifski, reactable, leaflet, geofacet, devtools, crosstalk, usethis +Config/testthat/edition: 3 +Config/testthat/parallel: true Copyright: © AEMET. See file COPYRIGHTS Encoding: UTF-8 LazyData: true diff --git a/NAMESPACE b/NAMESPACE index 2ad85401..a042da99 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -16,6 +16,7 @@ export(aemet_monthly_period) export(aemet_monthly_period_all) export(aemet_normal_clim) export(aemet_normal_clim_all) +export(aemet_show_api_key) export(aemet_stations) export(climaemet_news) export(climatestripes_station) diff --git a/NEWS.md b/NEWS.md index 521ec2f6..d5f151e5 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,8 +1,10 @@ # climaemet (development version) - Migrate from **httr** to **httr2** (#50). +- Use progress bars in downloads thanks to **cli**. New argument + `progress = TRUE` in most functions. - It is possible to use several API keys to avoid API throttling, see - `?climaemet::aemet_api_key` (#53). `?climaemet::aemet_api_key`. + `?climaemet::aemet_api_key` (#53). - New helper function `dms2decdegrees_2()`. - Update `aemet_munic` with January 2024 data. diff --git a/R/aemet_api_key.R b/R/aemet_api_key.R index 81b28684..71c6bb82 100644 --- a/R/aemet_api_key.R +++ b/R/aemet_api_key.R @@ -4,27 +4,25 @@ #' #' @description #' This function will store your AEMET API key on your local machine so it can -#' be called securely without being stored in your code. After you have -#' installed your key, it can be called any time by typing -#' `Sys.getenv("AEMET_API_KEY")` and can be -#' used in package functions by simply typing `AEMET_API_KEY`. +#' be called securely without being stored in your code. #' #' Alternatively, you can install the API Key manually: -#' * Run `Sys.setenv(AEMET_API_KEY = "Your_Key")`. You would need to run this -#' command on each session (Similar to `install = FALSE`). -#' * Write this line on your .Renviron file: `AEMET_API_KEY = "Your_Key"` ( -#' same behavior than `install = TRUE`). This would store your API key -#' permanently. +#' - Run `Sys.setenv(AEMET_API_KEY = "Your_Key")`. You would need to run this +#' command on each session (Similar to `install = FALSE`). +#' - Write this line on your .Renviron file: `AEMET_API_KEY = "Your_Key"` +#' (same behavior than `install = TRUE`). This would store your API key +#' permanently. #' #' @return None #' #' @param apikey The API key provided to you from the AEMET formatted in quotes. #' A key can be acquired at -#' . +#' . You can install +#' several API Keys as a vector of characters, see **Details**. #' @param install if `TRUE`, will install the key in your local machine for #' use in future sessions. Defaults to `FALSE.` #' @param overwrite If this is set to `TRUE`, it will overwrite an existing -#' AEMET_API_KEY that you already have in local machine. +#' `AEMET_API_KEY` that you already have in local machine. #' #' @details #' You can pass several `apikey` values as a vector `c(api1, api2)`, in this @@ -62,7 +60,7 @@ aemet_api_key <- function(apikey, overwrite = FALSE, install = FALSE) { # Validate stopifnot(is.character(apikey), is.logical(overwrite), is.logical(install)) - + apikey <- trimws(apikey) if (install) { cachedir <- rappdirs::user_cache_dir("climaemet", "R") @@ -109,12 +107,13 @@ aemet_api_key <- function(apikey, overwrite = FALSE, install = FALSE) { #' #' @description #' The function would detect if an API Key is available on this session: -#' * If an API Key is already set as an environment variable it would be +#' - If an API Key is already set as an environment variable it would be #' preserved -#' * If no environment variable has been set and you have stored permanently +#' - If no environment variable has been set and you have stored permanently #' an API Key using [aemet_api_key()], the latter would be loaded. #' -#' @return `TRUE` or `FALSE` +#' @return +#' `TRUE` or `FALSE`. `aemet_show_api_key()` would display your stored API keys. #' #' @family aemet_auth #' @@ -122,10 +121,16 @@ aemet_api_key <- function(apikey, overwrite = FALSE, install = FALSE) { #' #' @param ... Ignored #' +#' @rdname aemet_detect_api_key #' #' @examples #' #' aemet_detect_api_key() +#' +#' # CAUTION: This may reveal API Keys +#' if (FALSE) { +#' aemet_show_api_key() +#' } aemet_detect_api_key <- function(...) { allvar <- Sys.getenv() @@ -166,6 +171,15 @@ aemet_detect_api_key <- function(...) { } } +#' @export +#' @rdname aemet_detect_api_key +aemet_show_api_key <- function(...) { + # Expose internal function + # nocov start + aemet_hlp_get_allkeys(...) + # nocov end +} + aemet_hlp_get_allkeys <- function(...) { allkeys <- Sys.getenv()[grepl("^AEMET_API", names(Sys.getenv()))] allkeys <- unname(as.character(allkeys)) diff --git a/R/aemet_api_query.R b/R/aemet_api_query.R index 1e62234e..ebfab413 100644 --- a/R/aemet_api_query.R +++ b/R/aemet_api_query.R @@ -7,7 +7,8 @@ #' #' @family aemet_api #' -#' @source +#' @source +#' . #' #' @param apidest Character string as destination URL. See #' . diff --git a/R/aemet_daily.R b/R/aemet_daily.R index 306cf300..9b739baa 100644 --- a/R/aemet_daily.R +++ b/R/aemet_daily.R @@ -13,21 +13,21 @@ #' #' @family aemet_api_data #' -#' @param start,end Character string with start and end date. See Details. +#' @param start,end Character string with start and end date. See **Details**. #' #' @inheritParams aemet_last_obs #' #' @details #' `start` and `end` parameters should be: -#' * For `aemet_daily_clim()`: A `Date` object or a string with format: -#' YYYY-MM-DD (2020-12-31) coercible with [as.Date()]. -#' * For `aemet_daily_period()` and `aemet_daily_period_all()`: A string -#' representing the year(s) to be extracted: "2020", "2018". +#' - For `aemet_daily_clim()`: A `Date` object or a string with format: +#' `YYYY-MM-DD` (`"2020-12-31"`) coercible with [as.Date()]. +#' - For `aemet_daily_period()` and `aemet_daily_period_all()`: A string +#' representing the year(s) to be extracted: `"2020"`, `"2018"`. #' #' # API Key #' You need to set your API Key globally using [aemet_api_key()]. #' -#' @return A [`tibble`][tibble::tibble()] or a \CRANpkg{sf} object +#' @return A [`tibble`][tibble::tibble()] or a \CRANpkg{sf} object. #' #' @examplesIf aemet_detect_api_key() #' @@ -44,129 +44,163 @@ #' @export aemet_daily_clim <- function(station = "all", start = Sys.Date() - 7, end = Sys.Date(), verbose = FALSE, - return_sf = FALSE, extract_metadata = FALSE) { - # Validate inputs---- + return_sf = FALSE, extract_metadata = FALSE, + progress = TRUE) { + # 1. Validate inputs---- if (is.null(station)) { stop("Station can't be missing") } station <- as.character(station) - # For metadata + # For metadata make simplified version if (isTRUE(extract_metadata)) { - if (tolower(station[1]) == "all") station <- default_station - station <- station[1] + station <- default_station start <- Sys.Date() - 7 end <- Sys.Date() } - start_conv <- as.Date(start) - end_conv <- as.Date(end) - - if (is.na(start_conv) || is.na(end_conv)) { - stop("Error parsing start/end dates.Use YYYY-MM-DD format") - } + start_conv <- min(Sys.Date(), as.Date(start)) + end_conv <- min(Sys.Date(), as.Date(end)) stopifnot(is.logical(return_sf)) stopifnot(is.logical(verbose)) - # Call API---- + # 2. Call API---- - ## All ---- - if ("all" %in% tolower(station)) { - # Same day - if (start_conv == end_conv) { - seq_all <- sort(c(start_conv, end_conv)) - } else { - # Max request: 31 days - seq_all <- seq(start_conv, end_conv, by = "31 days") - seq_all <- pmin(end_conv, c(start_conv, end_conv, seq_all)) - seq_all <- sort(unique(seq_all)) - } + ## Metadata ---- + if (extract_metadata) { + apidest <- paste0( + "/api/valores/climatologicos/diarios/datos/fechaini/", + start_conv, "T00:00:00UTC/fechafin/", end_conv, + "T23:59:59UTC/estacion/", station + ) + final_result <- get_metadata_aemet(apidest = apidest, verbose = verbose) + return(final_result) + } - final_result <- NULL - - for (i in seq_len(length(seq_all) - 1)) { - apidest <- - paste0( - "/api/valores/climatologicos/diarios/datos/fechaini/", - seq_all[i], - "T00:00:00UTC/fechafin/", - seq_all[i + 1], - "T23:59:59UTC/todasestaciones" - ) - final_result <- dplyr::bind_rows( - final_result, - get_data_aemet(apidest = apidest, verbose = verbose) - ) - } - } else { - ## Single request---- - # Max: 5 years - # Same day - if (start_conv == end_conv) { - seq_all <- sort(c(start_conv, end_conv)) + ## Normal call ---- + + # Extract data creating a master table + # In all select API endpoint all + if (any(station == "all")) station <- "all" + + # Create data frame with cuts + + # Cut by time, max 6 months, we use cuts of 5 months + # except in all, that is 15 days + nr <- seq_len(length(station)) + + db_cuts <- lapply(nr, function(x) { + id <- station[x] + int <- switch(id, + "all" = "-14 days", + "-5 months" + ) + + seq_d <- unique(c(start_conv, seq(end_conv, start_conv, int), end_conv)) + seq_d <- sort(pmin(Sys.Date(), seq_d)) + # Single day: repeat + if (length(seq_d) == 1) seq_d <- rep(seq_d, 2) + + # Create final data.frame + df_end <- data.frame( + st = seq_d[-length(seq_d)], + en = seq_d[-1] + ) + df_end$id <- id + df_end$st <- paste0(df_end$st, "T00:00:00UTC") + df_end$en <- paste0(df_end$en, "T23:59:59UTC") + + df_end + }) + + db_cuts <- dplyr::bind_rows(db_cuts) + # Done + + # Make calls on loop for progress bar + final_result <- list() # Store results + + # Prepare progress bar + + ln <- seq_len(nrow(db_cuts)) + + # Deactive progressbar if verbose + if (verbose) progress <- FALSE + if (!cli::is_dynamic_tty()) progress <- FALSE + + # nolint start + # nocov start + if (progress) { + opts <- options() + options( + cli.progress_bar_style = "fillsquares", cli.progress_show_after = 3, + cli.spinner = "clock" + ) + + cli::cli_progress_bar( + format = paste0( + "{cli::pb_spin} AEMET API ({cli::pb_current}/{cli::pb_total}) ", + "| {cli::pb_bar} {cli::pb_percent} ", + "| ETA:{cli::pb_eta} [{cli::pb_elapsed}]" + ), + total = nrow(db_cuts), clear = FALSE + ) + } + + # nocov end + # nolint end + + ### API Loop ---- + for (id in ln) { + this <- db_cuts[id, ] + apidest <- paste0( + "/api/valores/climatologicos/diarios/datos/fechaini/", + this$st, "/fechafin/", this$en + ) + if (this$id == "all") { + apidest <- paste0(apidest, "/todasestaciones") } else { - seq_all <- seq(start_conv, end_conv, by = "4 years") - seq_all <- pmin(end_conv, c(start_conv, end_conv, seq_all)) - seq_all <- sort(unique(seq_all)) - } - final_result <- NULL - # Vectorise - for (s in station) { - for (i in seq_len(length(seq_all) - 1)) { - apidest <- - paste0( - "/api/valores/climatologicos/diarios/datos/fechaini/", - seq_all[i], - "T00:00:00UTC/fechafin/", - seq_all[i + 1], - "T23:59:59UTC/estacion/", - s - ) - - if (isTRUE(extract_metadata)) { - final_result <- get_metadata_aemet( - apidest = apidest, - verbose = verbose - ) - } else { - final_result <- - dplyr::bind_rows( - final_result, - get_data_aemet( - apidest = apidest, - verbose = verbose - ) - ) - } - } + apidest <- paste0(apidest, "/estacion/", this$id) } + if (progress) cli::cli_progress_update() # nocov + df <- get_data_aemet(apidest = apidest, verbose = verbose) + + final_result <- c(final_result, list(df)) } - final_result <- dplyr::distinct(final_result) - if (isTRUE(extract_metadata)) { - return(final_result) + + # nolint start + # nocov start + if (progress) { + cli::cli_progress_done() + options( + cli.progress_bar_style = opts$cli.progress_bar_style, + cli.progress_show_after = opts$cli.progress_show_after, + cli.spinner = opts$cli.spinner + ) } - # Guess formats + # nocov end + # nolint end + + # Final tweaks + final_result <- dplyr::bind_rows(final_result) + final_result <- dplyr::as_tibble(final_result) + final_result <- dplyr::distinct(final_result) final_result <- aemet_hlp_guess(final_result, "indicativo") # Check spatial---- if (return_sf) { # Coordinates from statios - sf_stations <- - aemet_stations(verbose = verbose, return_sf = FALSE) - sf_stations <- - sf_stations[c("indicativo", "latitud", "longitud")] + sf_stations <- aemet_stations(verbose = verbose, return_sf = FALSE) + sf_stations <- sf_stations[c("indicativo", "latitud", "longitud")] - final_result <- dplyr::left_join(final_result, - sf_stations, + final_result <- dplyr::left_join(final_result, sf_stations, by = "indicativo" ) - final_result <- - aemet_hlp_sf(final_result, "latitud", "longitud", verbose) + final_result <- aemet_hlp_sf(final_result, "latitud", "longitud", verbose) } - return(final_result) + final_result } @@ -175,9 +209,8 @@ aemet_daily_clim <- function(station = "all", start = Sys.Date() - 7, #' @export aemet_daily_period <- function(station, start = as.integer(format(Sys.Date(), "%Y")), - end = start, - verbose = FALSE, return_sf = FALSE, - extract_metadata = FALSE) { + end = start, verbose = FALSE, return_sf = FALSE, + extract_metadata = FALSE, progress = TRUE) { # Validate inputs---- if (is.null(start)) { stop("Start year can't be missing") @@ -198,10 +231,9 @@ aemet_daily_period <- function(station, # Call API---- # Via daily clim - final_result <- - aemet_daily_clim(station, fdoy, ldoy, verbose, return_sf, - extract_metadata = extract_metadata - ) + final_result <- aemet_daily_clim(station, fdoy, ldoy, verbose, return_sf, + extract_metadata = extract_metadata, progress = progress + ) return(final_result) } @@ -212,8 +244,8 @@ aemet_daily_period <- function(station, #' @export aemet_daily_period_all <- function(start = as.integer(format(Sys.Date(), "%Y")), end = start, verbose = FALSE, - return_sf = FALSE, - extract_metadata = FALSE) { + return_sf = FALSE, extract_metadata = FALSE, + progress = TRUE) { # Validate inputs---- if (is.null(start)) { stop("Start year can't be missing") @@ -232,13 +264,16 @@ aemet_daily_period_all <- function(start = as.integer(format(Sys.Date(), "%Y")), } # Rest of parameters validated in aemet_daily_clim + # nocov start + # Dont test this as it would exhaust the API calls fdoy <- paste0(start, "-01-01") ldoy <- paste0(end, "-12-31") # Call API---- # via aemet_daily_clim data_all <- aemet_daily_clim("all", fdoy, ldoy, verbose, return_sf, - extract_metadata = extract_metadata + extract_metadata = extract_metadata, progress = progress ) - return(data_all) + data_all + # nocov end } diff --git a/R/aemet_extremes.R b/R/aemet_extremes.R index dfb247b1..ab6a5184 100644 --- a/R/aemet_extremes.R +++ b/R/aemet_extremes.R @@ -8,17 +8,19 @@ #' @family aemet_api_data #' #' @param station Character string with station identifier code(s) -#' (see [aemet_stations()]) +#' (see [aemet_stations()]). #' -#' @param parameter Character string as temperature ("T"), -#' precipitation ("P") or wind ("V") parameter. +#' @param parameter Character string as temperature (`"T"`), +#' precipitation (`"P"`) or wind (`"V"`) parameter. #' #' @inheritParams aemet_last_obs #' #' @inheritSection aemet_daily_clim API Key #' #' @seealso [aemet_api_key()] -#' @return A [`tibble`][tibble::tibble()] or a \CRANpkg{sf} object +#' @return +#' A [`tibble`][tibble::tibble()] or a \CRANpkg{sf} object. If the function +#' finds an error when parsing it would return the result as a `list()` object. #' #' @examplesIf aemet_detect_api_key() #' library(tibble) @@ -28,15 +30,15 @@ aemet_extremes_clim <- function(station = NULL, parameter = "T", verbose = FALSE, return_sf = FALSE, - extract_metadata = FALSE) { - # Validate parameters---- + extract_metadata = FALSE, progress = TRUE) { + # 1. Validate parameters---- if (is.null(station)) { stop("Station can't be missing") } station <- as.character(station) - if (isTRUE(extract_metadata)) station <- station[1] + if (isTRUE(extract_metadata)) station <- default_station if (is.null(parameter)) { stop("Parameter can't be missing") @@ -50,54 +52,104 @@ aemet_extremes_clim <- function(station = NULL, parameter = "T", stop("Parameter should be one of 'T', 'P', 'V'") } - # Single request---- - # Vectorize function - final_result <- NULL - - for (i in seq_len(length(station))) { - apidest <- - paste0( - "/api/valores/climatologicos/valoresextremos/parametro/", - parameter, - "/estacion/", - station[i] - ) - - if (isTRUE(extract_metadata)) { - final_result <- get_metadata_aemet( - apidest = apidest, - verbose = verbose - ) - } else { - final_result <- - dplyr::bind_rows( - final_result, - get_data_aemet(apidest, verbose) - ) - } + # 2. Call API---- + + ## Metadata ---- + + if (extract_metadata) { + apidest <- paste0( + "/api/valores/climatologicos/valoresextremos/parametro/", + parameter, "/estacion/", default_station + ) + + final_result <- get_metadata_aemet( + apidest = apidest, + verbose = verbose + ) + return(final_result) } - final_result <- dplyr::distinct(final_result) - if (isTRUE(extract_metadata)) { + + ## Normal call ---- + + # Make calls on loop for progress bar + final_result <- list() # Store results + + # Deactive progressbar if verbose + if (verbose) progress <- FALSE + if (!cli::is_dynamic_tty()) progress <- FALSE + + # nolint start + # nocov start + if (progress) { + opts <- options() + options( + cli.progress_bar_style = "fillsquares", + cli.progress_show_after = 3, + cli.spinner = "clock" + ) + + cli::cli_progress_bar( + format = paste0( + "{cli::pb_spin} AEMET API ({cli::pb_current}/{cli::pb_total}) ", + "| {cli::pb_bar} {cli::pb_percent} ", + "| ETA:{cli::pb_eta} [{cli::pb_elapsed}]" + ), + total = length(station), clear = FALSE + ) + } + + # nocov end + # nolint end + + for (id in station) { + apidest <- paste0( + "/api/valores/climatologicos", + "/valoresextremos/parametro/", parameter, "/estacion/", + id + ) + + + if (progress) cli::cli_progress_update() # nocov + df <- get_data_aemet(apidest = apidest, verbose = verbose) + + final_result <- c(final_result, list(df)) + } + + # nolint start + # nocov start + if (progress) { + cli::cli_progress_done() + options( + cli.progress_bar_style = opts$cli.progress_bar_style, + cli.progress_show_after = opts$cli.progress_show_after, + cli.spinner = opts$cli.spinner + ) + } + # nocov end + # nolint end + + bindtry <- try(dplyr::bind_rows(final_result), silent = TRUE) + if (inherits(bindtry, "try-error")) { + message("Can't convert to tibble, return list") return(final_result) } + final_result <- dplyr::bind_rows(final_result) + final_result <- dplyr::as_tibble(final_result) + final_result <- dplyr::distinct(final_result) + final_result <- aemet_hlp_guess(final_result, "indicativo", dec_mark = ".") - # Guess formats - final_result <- - aemet_hlp_guess(final_result, "indicativo", dec_mark = ".") # Check spatial---- if (return_sf) { # Coordinates from stations - sf_stations <- - aemet_stations(verbose, return_sf = FALSE) - sf_stations <- - sf_stations[c("indicativo", "latitud", "longitud")] - - final_result <- - dplyr::left_join(final_result, sf_stations, by = "indicativo") - final_result <- - aemet_hlp_sf(final_result, "latitud", "longitud", verbose) + sf_stations <- aemet_stations(verbose, return_sf = FALSE) + sf_stations <- sf_stations[c("indicativo", "latitud", "longitud")] + + final_result <- dplyr::left_join(final_result, sf_stations, + by = "indicativo" + ) + final_result <- aemet_hlp_sf(final_result, "latitud", "longitud", verbose) } - return(final_result) + final_result } diff --git a/R/aemet_forecast_daily.R b/R/aemet_forecast_daily.R index 3ed184b5..21213532 100644 --- a/R/aemet_forecast_daily.R +++ b/R/aemet_forecast_daily.R @@ -1,59 +1,106 @@ #' @export #' @rdname aemet_forecast -aemet_forecast_daily <- function(x, verbose = FALSE, extract_metadata = FALSE) { - if (all(verbose, extract_metadata, length(x) > 1)) { - x <- x[1] - message("Extracting metadata for ", x, " only") +aemet_forecast_daily <- function(x, verbose = FALSE, extract_metadata = FALSE, + progress = TRUE) { + # 1. API call ----- + + ## Metadata ---- + if (extract_metadata) { + mun <- climaemet::aemet_munic + x <- mun$municipio[1] + + meta <- get_metadata_aemet( + apidest = paste0("/api/prediccion/especifica/municipio/diaria/", x), + verbose = verbose + ) + meta <- aemet_hlp_meta_forecast(meta) + return(meta) } - single <- lapply(x, function(x) { - res <- try( - aemet_forecast_daily_single(x, - verbose = verbose, - extract_metadata = extract_metadata + + ## Normal call ---- + + # Make calls on loop for progress bar + final_result <- list() # Store results + + # Deactive progressbar if verbose + if (verbose) progress <- FALSE + if (!cli::is_dynamic_tty()) progress <- FALSE + + # nolint start + # nocov start + if (progress) { + opts <- options() + options( + cli.progress_bar_style = "fillsquares", + cli.progress_show_after = 3, + cli.spinner = "clock" + ) + + cli::cli_progress_bar( + format = paste0( + "{cli::pb_spin} AEMET API ({cli::pb_current}/{cli::pb_total}) ", + "| {cli::pb_bar} {cli::pb_percent} ", + "| ETA:{cli::pb_eta} [{cli::pb_elapsed}]" ), - silent = TRUE + total = length(x), clear = FALSE ) - if (inherits(res, "try-error")) { + } + + # nocov end + # nolint end + + for (id in x) { + if (progress) cli::cli_progress_update() # nocov + df <- try(aemet_forecast_daily_single(id, verbose = verbose), silent = TRUE) + + if (inherits(df, "try-error")) { message( - "\nAEMET API call for '", x, "' returned an error\n", + "\nAEMET API call for '", id, "' returned an error\n", "Return NULL for this query" ) - return(NULL) + + df <- NULL } - return(res) - }) - bind <- dplyr::bind_rows(single) - if (extract_metadata) { - return(bind) + + final_result <- c(final_result, list(df)) + } + + + # nolint start + # nocov start + if (progress) { + cli::cli_progress_done() + options( + cli.progress_bar_style = opts$cli.progress_bar_style, + cli.progress_show_after = opts$cli.progress_show_after, + cli.spinner = opts$cli.spinner + ) } + # nocov end + # nolint end + + + # Final tweaks + final_result <- dplyr::bind_rows(final_result) # Preserve format - bind$id <- sprintf("%05d", as.numeric(bind$id)) - bind <- aemet_hlp_guess(bind, preserve = c("id", "municipio")) + final_result$id <- sprintf("%05d", as.numeric(final_result$id)) + final_result <- dplyr::as_tibble(final_result) + final_result <- dplyr::distinct(final_result) + final_result <- aemet_hlp_guess(final_result, + preserve = c("id", "municipio") + ) - return(bind) + final_result } -aemet_forecast_daily_single <- function(x, verbose = FALSE, - extract_metadata = FALSE) { +aemet_forecast_daily_single <- function(x, verbose = FALSE) { if (is.numeric(x)) x <- sprintf("%05d", x) - if (isTRUE(extract_metadata)) { - meta <- - get_metadata_aemet( - apidest = paste0("/api/prediccion/especifica/municipio/diaria/", x), - verbose = verbose - ) - meta <- aemet_hlp_meta_forecast(meta) - return(meta) - } - - - pred <- - get_data_aemet( - apidest = paste0("/api/prediccion/especifica/municipio/diaria/", x), - verbose = verbose - ) + pred <- get_data_aemet( + apidest = paste0("/api/prediccion/especifica/municipio/diaria/", x), + verbose = verbose + ) pred$elaborado <- as.POSIXct(gsub("T", " ", pred$elaborado), tz = "Europe/Madrid" diff --git a/R/aemet_forecast_hourly.R b/R/aemet_forecast_hourly.R index 41298af8..1cd8bfdb 100644 --- a/R/aemet_forecast_hourly.R +++ b/R/aemet_forecast_hourly.R @@ -7,11 +7,12 @@ #' #' @param x A vector of municipality codes to extract. For convenience, #' \CRANpkg{climaemet} provides this data on the dataset [aemet_munic] -#' (see `municipio` field) as of January 2020. +#' (see `municipio` field) as of January 2024. #' @param extract_metadata Logical `TRUE/FALSE`. On `TRUE` the output is #' a [`tibble`][tibble::tibble()] with the description of the fields. See also #' [get_metadata_aemet()]. #' @inheritParams get_data_aemet +#' @inheritParams aemet_last_obs #' #' @inheritSection aemet_daily_clim API Key #' @@ -20,7 +21,11 @@ #' #' @export #' @rdname aemet_forecast -#' @seealso [aemet_munic] for municipality codes. +#' @seealso +#' [aemet_munic] for municipality codes and \CRANpkg{mapSpain} package for +#' working with `sf` objects of municipalities (see +#' `mapSpain::esp_get_munic()`). +#' #' #' @details #' @@ -100,57 +105,109 @@ #' ) #' ) aemet_forecast_hourly <- function(x, verbose = FALSE, - extract_metadata = FALSE) { - if (all(verbose, extract_metadata, length(x) > 1)) { - x <- x[1] - message("Extracting metadata for ", x, " only") + extract_metadata = FALSE, progress = TRUE) { + # 1. API call ----- + + ## Metadata ---- + if (extract_metadata) { + mun <- climaemet::aemet_munic + x <- mun$municipio[1] + + meta <- get_metadata_aemet( + apidest = paste0("/api/prediccion/especifica/municipio/horaria/", x), + verbose = verbose + ) + meta <- aemet_hlp_meta_forecast(meta) + return(meta) } - single <- lapply(x, function(x) { - res <- try( - aemet_forecast_hourly_single(x, - verbose = verbose, - extract_metadata = extract_metadata + + ## Normal call ---- + + # Make calls on loop for progress bar + final_result <- list() # Store results + + # Deactive progressbar if verbose + if (verbose) progress <- FALSE + if (!cli::is_dynamic_tty()) progress <- FALSE + + # nolint start + # nocov start + if (progress) { + opts <- options() + options( + cli.progress_bar_style = "fillsquares", + cli.progress_show_after = 3, + cli.spinner = "clock" + ) + + cli::cli_progress_bar( + format = paste0( + "{cli::pb_spin} AEMET API ({cli::pb_current}/{cli::pb_total}) ", + "| {cli::pb_bar} {cli::pb_percent} ", + "| ETA:{cli::pb_eta} [{cli::pb_elapsed}]" ), + total = length(x), clear = FALSE + ) + } + + # nocov end + # nolint end + + + for (id in x) { + if (progress) cli::cli_progress_update() # nocov + df <- try(aemet_forecast_hourly_single(id, verbose = verbose), silent = TRUE ) - if (inherits(res, "try-error")) { + if (inherits(df, "try-error")) { message( - "\nAEMET API call for '", x, "' returned an error\n", + "\nAEMET API call for '", id, "' returned an error\n", "Return NULL for this query" ) - return(NULL) + + df <- NULL } - return(res) - }) - bind <- dplyr::bind_rows(single) - if (extract_metadata) { - return(bind) + + final_result <- c(final_result, list(df)) + } + + # nolint start + # nocov start + if (progress) { + cli::cli_progress_done() + options( + cli.progress_bar_style = opts$cli.progress_bar_style, + cli.progress_show_after = opts$cli.progress_show_after, + cli.spinner = opts$cli.spinner + ) } + # nocov end + # nolint end + + + + # Final tweaks + final_result <- dplyr::bind_rows(final_result) # Preserve format - bind$id <- sprintf("%05d", as.numeric(bind$id)) - bind <- aemet_hlp_guess(bind, preserve = c("id", "municipio")) - return(bind) + final_result$id <- sprintf("%05d", as.numeric(final_result$id)) + final_result <- dplyr::as_tibble(final_result) + final_result <- dplyr::distinct(final_result) + final_result <- aemet_hlp_guess(final_result, + preserve = c("id", "municipio") + ) + + final_result } -aemet_forecast_hourly_single <- function(x, verbose = FALSE, - extract_metadata = FALSE) { +aemet_forecast_hourly_single <- function(x, verbose = FALSE) { if (is.numeric(x)) x <- sprintf("%05d", x) - if (isTRUE(extract_metadata)) { - meta <- - get_metadata_aemet( - apidest = paste0("/api/prediccion/especifica/municipio/horaria/", x), - verbose = verbose - ) - meta <- aemet_hlp_meta_forecast(meta) - return(meta) - } - - pred <- - get_data_aemet( - apidest = paste0("/api/prediccion/especifica/municipio/horaria/", x), - verbose = verbose - ) + pred <- get_data_aemet( + apidest = paste0( + "/api/prediccion/especifica/municipio/horaria/", x + ), + verbose = verbose + ) pred$elaborado <- as.POSIXct(gsub("T", " ", pred$elaborado), diff --git a/R/aemet_last_obs.R b/R/aemet_last_obs.R index 66bf91c7..d7684217 100644 --- a/R/aemet_last_obs.R +++ b/R/aemet_last_obs.R @@ -18,6 +18,8 @@ #' Should the function return an [`sf`][sf::st_sf] spatial object? If `FALSE` #' (the default value) it returns a [`tibble`][tibble::tibble()]. Note that #' you need to have the \CRANpkg{sf} package installed. +#' @param progress Logical, display a [cli::cli_progress_bar()] object. If +#' `verbose = TRUE` won't be displayed. #' #' @return A [`tibble`][tibble::tibble()] or a \CRANpkg{sf} object #' @@ -28,9 +30,9 @@ #' library(tibble) #' obs <- aemet_last_obs(c("9434", "3195")) #' glimpse(obs) -aemet_last_obs <- function(station = "all", verbose = FALSE, - return_sf = FALSE, extract_metadata = FALSE) { - # Validate inputs---- +aemet_last_obs <- function(station = "all", verbose = FALSE, return_sf = FALSE, + extract_metadata = FALSE, progress = TRUE) { + # 1. Validate inputs---- if (is.null(station)) { stop("Station can't be missing") } @@ -45,50 +47,90 @@ aemet_last_obs <- function(station = "all", verbose = FALSE, if (tolower(station[1]) == "all") station <- default_station station <- station[1] } - # Call API---- - ## All---- - if ("all" %in% tolower(station)) { - final_result <- - get_data_aemet("/api/observacion/convencional/todas", verbose) - } else { - # Single request---- - # Vectorize function - final_result <- NULL - - for (i in seq_len(length(station))) { - apidest <- paste0( - "/api/observacion/convencional/datos/estacion/", - station[i] - ) - - if (isTRUE(extract_metadata)) { - final_result <- get_metadata_aemet( - apidest = apidest, - verbose = verbose - ) - } else { - final_result <- - dplyr::bind_rows( - final_result, - get_data_aemet(apidest, verbose) - ) - } - } - } + # 2. Call API---- + + ## Metadata ----- - final_result <- dplyr::distinct(final_result) if (isTRUE(extract_metadata)) { + final_result <- get_metadata_aemet( + apidest = "/api/observacion/convencional/todas", + verbose = verbose + ) return(final_result) } - # Guess formats---- - final_result <- - aemet_hlp_guess(final_result, "idema", dec_mark = ".") + ## Normal call ---- + + if (any(station == "all")) station <- "all" + + # Make calls on loop for progress bar + final_result <- list() # Store results + + # Deactive progressbar if verbose + if (verbose) progress <- FALSE + if (!cli::is_dynamic_tty()) progress <- FALSE + + # nolint start + # nocov start + if (progress) { + opts <- options() + options( + cli.progress_bar_style = "fillsquares", + cli.progress_show_after = 3, + cli.spinner = "clock" + ) + + cli::cli_progress_bar( + format = paste0( + "{cli::pb_spin} AEMET API ({cli::pb_current}/{cli::pb_total}) ", + "| {cli::pb_bar} {cli::pb_percent} ", + "| ETA:{cli::pb_eta} [{cli::pb_elapsed}]" + ), + total = length(station), clear = FALSE + ) + } + + # nocov end + # nolint end + + for (id in station) { + if (id == "all") { + apidest <- "/api/observacion/convencional/todas" + } else { + apidest <- paste0("/api/observacion/convencional/datos/estacion/", id) + } + + + if (progress) cli::cli_progress_update() # nocov + df <- get_data_aemet(apidest = apidest, verbose = verbose) + + final_result <- c(final_result, list(df)) + } + + # nolint start + # nocov start + + if (progress) { + cli::cli_progress_done() + options( + cli.progress_bar_style = opts$cli.progress_bar_style, + cli.progress_show_after = opts$cli.progress_show_after, + cli.spinner = opts$cli.spinner + ) + } + + # nocov end + # nolint end + + final_result <- dplyr::bind_rows(final_result) + final_result <- dplyr::as_tibble(final_result) + final_result <- dplyr::distinct(final_result) + final_result <- aemet_hlp_guess(final_result, "idema") # Check spatial---- if (return_sf) { final_result <- aemet_hlp_sf(final_result, "lat", "lon", verbose) } - return(final_result) + final_result } diff --git a/R/aemet_monthly.R b/R/aemet_monthly.R index 53e196f5..5d9c56eb 100644 --- a/R/aemet_monthly.R +++ b/R/aemet_monthly.R @@ -14,15 +14,15 @@ #' @family aemet_api_data #' #' @param station Character string with station identifier code(s) -#' (see [aemet_stations()]) +#' (see [aemet_stations()]). #' -#' @param year Numeric value as date (format: YYYY). +#' @param year Numeric value as date (format: `YYYY`). #' #' @inheritParams aemet_last_obs #' #' @inheritSection aemet_daily_clim API Key #' -#' @return A [`tibble`][tibble::tibble()] or a \CRANpkg{sf} object +#' @return A [`tibble`][tibble::tibble()] or a \CRANpkg{sf} object. #' #' @examplesIf aemet_detect_api_key() #' @@ -32,14 +32,14 @@ #' @export aemet_monthly_clim <- function(station = NULL, year = as.integer(format(Sys.Date(), "%Y")), - verbose = FALSE, - return_sf = FALSE, extract_metadata = FALSE) { - # Validate inputs---- + verbose = FALSE, return_sf = FALSE, + extract_metadata = FALSE, progress = TRUE) { + # 1. Validate inputs---- if (is.null(station)) { stop("Station can't be missing") } station <- as.character(station) - if (isTRUE(extract_metadata)) station <- station[1] + if (isTRUE(extract_metadata)) station <- default_station if (!is.numeric(year)) { stop("Year need to be numeric") @@ -47,73 +47,124 @@ aemet_monthly_clim <- function(station = NULL, stopifnot(is.logical(verbose)) stopifnot(is.logical(return_sf)) - # Call API---- - # Vectorize function - final_result <- NULL + today <- as.integer(format(Sys.Date(), "%Y")) + + year <- min(year, today) + # 2. Call API---- + + ## Metadata ---- + if (extract_metadata) { + apidest <- paste0( + "/api/valores/climatologicos/mensualesanuales/datos", + "/anioini/", year, "/aniofin/", year, "/estacion/", + station + ) + final_result <- get_metadata_aemet(apidest = apidest, verbose = verbose) + return(final_result) + } + + ## Normal call ---- + + # Make calls on loop for progress bar + final_result <- list() # Store results + + # Deactive progressbar if verbose + if (verbose) progress <- FALSE + if (!cli::is_dynamic_tty()) progress <- FALSE + + # nolint start + # nocov start + if (progress) { + opts <- options() + options( + cli.progress_bar_style = "fillsquares", + cli.progress_show_after = 3, + cli.spinner = "clock" + ) - for (i in seq_len(length(station))) { - apidest <- - paste0( - "/api/valores/climatologicos/mensualesanuales/datos/anioini/", - year, - "/aniofin/", - year, - "/estacion/", - station[i] - ) - - if (isTRUE(extract_metadata)) { - final_result <- get_metadata_aemet( - apidest = apidest, - verbose = verbose - ) - } else { - final_result <- - dplyr::bind_rows(final_result, get_data_aemet(apidest, verbose)) + cli::cli_progress_bar( + format = paste0( + "{cli::pb_spin} AEMET API ({cli::pb_current}/{cli::pb_total}) ", + "| {cli::pb_bar} {cli::pb_percent} ", + "| ETA:{cli::pb_eta} [{cli::pb_elapsed}]" + ), + total = length(station), clear = FALSE + ) + } + + # nocov end + # nolint end + + for (id in station) { + apidest <- paste0( + "/api/valores/climatologicos/mensualesanuales/datos", + "/anioini/", year, "/aniofin/", year, "/estacion/", + id + ) + + if (progress) cli::cli_progress_update() # nocov + df <- get_data_aemet(apidest = apidest, verbose = verbose) + + for (i in seq_len(9)) { + patt <- paste0("-", i, "$") + newpat <- paste0("-0", i) + df$fecha <- gsub(patt, newpat, df$fecha) } + + df <- df[order(df$fecha), ] + + final_result <- c(final_result, list(df)) } - final_result <- dplyr::distinct(final_result) - if (isTRUE(extract_metadata)) { - return(final_result) + + # nolint start + # nocov start + if (progress) { + cli::cli_progress_done() + options( + cli.progress_bar_style = opts$cli.progress_bar_style, + cli.progress_show_after = opts$cli.progress_show_after, + cli.spinner = opts$cli.spinner + ) } + # nocov end + # nolint end + + + + # Final tweaks + final_result <- dplyr::bind_rows(final_result) + final_result <- dplyr::as_tibble(final_result) + final_result <- dplyr::distinct(final_result) + final_result <- aemet_hlp_guess(final_result, "indicativo", dec_mark = ".") - # Guess formats - final_result <- - aemet_hlp_guess(final_result, "indicativo", dec_mark = ".") # Check spatial---- if (return_sf) { # Coordinates from stations - sf_stations <- - aemet_stations(verbose, return_sf = FALSE) - sf_stations <- - sf_stations[c("indicativo", "latitud", "longitud")] + sf_stations <- aemet_stations(verbose, return_sf = FALSE) + sf_stations <- sf_stations[c("indicativo", "latitud", "longitud")] - final_result <- - dplyr::left_join(final_result, sf_stations, by = "indicativo") - final_result <- - aemet_hlp_sf(final_result, "latitud", "longitud", verbose) + final_result <- dplyr::left_join(final_result, sf_stations, + by = "indicativo" + ) + final_result <- aemet_hlp_sf(final_result, "latitud", "longitud", verbose) } - - return(final_result) + final_result } #' @rdname aemet_monthly #' -#' @param start Numeric value as start year (format: YYYY). +#' @param start Numeric value as start year (format: `YYYY`). #' -#' @param end Numeric value as end year (format: YYYY). +#' @param end Numeric value as end year (format: `YYYY`). #' #' @export aemet_monthly_period <- function(station = NULL, - start = as.integer(format( - Sys.Date(), - "%Y" - )), - end = start, - verbose = FALSE, return_sf = FALSE, - extract_metadata = FALSE) { - # Validate inputs---- + start = as.integer(format(Sys.Date(), "%Y")), + end = start, verbose = FALSE, + return_sf = FALSE, extract_metadata = FALSE, + progress = TRUE) { + # 1. Validate inputs---- if (is.null(station)) { stop("Station can't be missing") } @@ -129,48 +180,150 @@ aemet_monthly_period <- function(station = NULL, # The rest of parameters are validated in aemet_monthly_clim final_result <- NULL - # Call API---- - # via aemet_monthly_clim - for (y in seq(start, end, by = 1)) { - this_y <- aemet_monthly_clim( - station = station, - year = y, + # 2. Call API---- + + ## Metadata ---- + if (extract_metadata) { + # Use monthly clim + final_result <- aemet_monthly_clim( + station = station[1], verbose = verbose, - return_sf = FALSE, - extract_metadata = extract_metadata + extract_metadata = TRUE + ) + return(final_result) + } + + + # Normal call + # Cut by max 3 years, we use cuts of 3 years + nr <- seq_len(length(station)) + + db_cuts <- lapply(nr, function(x) { + id <- station[x] + + curr <- as.integer(format(Sys.Date(), "%Y")) + + seq_d <- pmin(c(seq(end, start, by = -3), start, end), curr) + seq_d <- sort(unique(seq_d)) + + + # Single year: repeat + if (length(seq_d) == 1) seq_d <- rep(seq_d, 2) + + # Create final data.frame + df_end <- data.frame( + st = seq_d[-length(seq_d)], + en = seq_d[-1] ) + df_end$id <- id - final_result <- dplyr::bind_rows(final_result, this_y) + df_end + }) + + db_cuts <- dplyr::bind_rows(db_cuts) + db_cuts <- dplyr::distinct(db_cuts) + # Done + + # Make calls on loop for progress bar + # Prepare progress bar + + ln <- seq_len(nrow(db_cuts)) + + # Deactive progressbar if verbose + if (verbose) progress <- FALSE + if (!cli::is_dynamic_tty()) progress <- FALSE + + # nolint start + # nocov start + if (progress) { + opts <- options() + options( + cli.progress_bar_style = "fillsquares", cli.progress_show_after = 3, + cli.spinner = "clock" + ) + + cli::cli_progress_bar( + format = paste0( + "{cli::pb_spin} AEMET API ({cli::pb_current}/{cli::pb_total}) ", + "| {cli::pb_bar} {cli::pb_percent} ", + "| ETA:{cli::pb_eta} [{cli::pb_elapsed}]" + ), + total = nrow(db_cuts), clear = FALSE + ) } - if (isTRUE(extract_metadata)) { - return(final_result) + + # nocov end + # nolint end + + ### API Loop ---- + for (id in ln) { + this <- db_cuts[id, ] + apidest <- paste0( + "/api/valores/climatologicos/mensualesanuales/datos", + "/anioini/", this$st, "/aniofin/", this$en, "/estacion/", + this$id + ) + + + if (progress) cli::cli_progress_update() # nocov + df <- get_data_aemet(apidest = apidest, verbose = verbose) + + df <- get_data_aemet(apidest = apidest, verbose = verbose) + + for (i in seq_len(9)) { + patt <- paste0("-", i, "$") + newpat <- paste0("-0", i) + df$fecha <- gsub(patt, newpat, df$fecha) + } + + df <- df[order(df$fecha), ] + + final_result <- c(final_result, list(df)) + + + final_result <- c(final_result, list(df)) } + # nolint start + # nocov start + if (progress) { + cli::cli_progress_done() + options( + cli.progress_bar_style = opts$cli.progress_bar_style, + cli.progress_show_after = opts$cli.progress_show_after, + cli.spinner = opts$cli.spinner + ) + } + + # nocov end + # nolint end + + # Final tweaks + final_result <- dplyr::bind_rows(final_result) + final_result <- dplyr::as_tibble(final_result) + final_result <- dplyr::distinct(final_result) + final_result <- aemet_hlp_guess(final_result, "indicativo", dec_mark = ".") + # Check spatial---- if (return_sf) { # Coordinates from stations - sf_stations <- - aemet_stations(verbose, return_sf = FALSE) - sf_stations <- - sf_stations[c("indicativo", "latitud", "longitud")] + sf_stations <- aemet_stations(verbose, return_sf = FALSE) + sf_stations <- sf_stations[c("indicativo", "latitud", "longitud")] - final_result <- - dplyr::left_join(final_result, sf_stations, by = "indicativo") - final_result <- - aemet_hlp_sf(final_result, "latitud", "longitud", verbose) + final_result <- dplyr::left_join(final_result, sf_stations, + by = "indicativo" + ) + final_result <- aemet_hlp_sf(final_result, "latitud", "longitud", verbose) } - - return(final_result) + final_result } #' @rdname aemet_monthly #' #' @export aemet_monthly_period_all <- function( - start = as.integer(format(Sys.Date(), "%Y")), - end = start, - verbose = FALSE, return_sf = FALSE, - extract_metadata = FALSE) { + start = as.integer(format(Sys.Date(), "%Y")), end = start, verbose = FALSE, + return_sf = FALSE, extract_metadata = FALSE, progress = TRUE) { # Validate inputs---- if (is.null(start)) { stop("Start year can't be missing") @@ -193,44 +346,18 @@ aemet_monthly_period_all <- function( if (isTRUE(extract_metadata)) { stations <- data.frame(indicativo = default_station) } else { - stations <- aemet_stations(verbose = verbose) - } - if (verbose) { - message("Requesting ", nrow(stations), " stations") - } - final_result <- NULL - - for (i in stations$indicativo) { - if (verbose) { - message("Station: ", i) - } - - data_recover <- aemet_monthly_period( - station = i, - start = start, - end = end, - verbose = verbose, - return_sf = FALSE, - extract_metadata = extract_metadata - ) - final_result <- dplyr::bind_rows(final_result, data_recover) + stations <- aemet_stations(verbose = verbose) # nocov } - if (isTRUE(extract_metadata)) { - return(final_result) - } - # Check spatial---- - if (return_sf) { - # Coordinates from stations - sf_stations <- - aemet_stations(verbose, return_sf = FALSE) - sf_stations <- - sf_stations[c("indicativo", "latitud", "longitud")] - final_result <- - dplyr::left_join(final_result, sf_stations, by = "indicativo") - final_result <- - aemet_hlp_sf(final_result, "latitud", "longitud", verbose) - } + # nocov start + all <- aemet_monthly_period( + station = stations$indicativo, start = start, + end = end, verbose = verbose, + return_sf = return_sf, + extract_metadata = extract_metadata, + progress = progress + ) + # nocov end - return(final_result) + all } diff --git a/R/aemet_normal.R b/R/aemet_normal.R index 5ab6c1d7..08e550e4 100644 --- a/R/aemet_normal.R +++ b/R/aemet_normal.R @@ -11,12 +11,12 @@ #' Get normal climatology values for a station (or all the stations with #' `aemet_normal_clim_all()`. Standard climatology from 1981 to 2010. #' -#' @note Code modified from project -#' +#' @note +#' Code modified from project . #' #' @inheritParams aemet_last_obs #' -#' @return A [`tibble`][tibble::tibble()] or a \CRANpkg{sf} object +#' @return A [`tibble`][tibble::tibble()] or a \CRANpkg{sf} object. #' #' @inheritSection aemet_daily_clim API Key #' @@ -29,8 +29,8 @@ aemet_normal_clim <- function(station = NULL, verbose = FALSE, return_sf = FALSE, - extract_metadata = FALSE) { - # Validate inputs---- + extract_metadata = FALSE, progress = TRUE) { + # 1. Validate inputs---- if (is.null(station)) { stop("Station can't be missing") } @@ -40,59 +40,95 @@ aemet_normal_clim <- function(station = NULL, verbose = FALSE, station <- as.character(station) - if (isTRUE(extract_metadata)) station <- station[1] - # Call API---- - - # Single request---- - # Vectorize function - final_result <- NULL - - for (i in seq_len(length(station))) { - apidest <- - paste0( - "/api/valores/climatologicos/normales/estacion/", - station[i] - ) - if (isTRUE(extract_metadata)) { - final_result <- get_metadata_aemet( - apidest = apidest, - verbose = verbose - ) - } else { - final_result <- - dplyr::bind_rows( - final_result, - get_data_aemet(apidest, verbose) - ) - } - } - final_result <- dplyr::distinct(final_result) - if (isTRUE(extract_metadata)) { + if (isTRUE(extract_metadata)) station <- default_station + + # 2. Call API---- + + ## Metadata ---- + if (extract_metadata) { + apidest <- paste0( + "/api/valores/climatologicos/normales/estacion/", + station + ) + final_result <- get_metadata_aemet( + apidest = apidest, + verbose = verbose + ) return(final_result) } - # Guess formats---- - if (verbose) { - message("\nGuessing fields...") + + ## Normal call ---- + + # Make calls on loop for progress bar + final_result <- list() # Store results + + # Deactive progressbar if verbose + if (verbose) progress <- FALSE + if (!cli::is_dynamic_tty()) progress <- FALSE + + # nolint start + # nocov start + if (progress) { + opts <- options() + options( + cli.progress_bar_style = "fillsquares", + cli.progress_show_after = 3, + cli.spinner = "clock" + ) + + cli::cli_progress_bar( + format = paste0( + "{cli::pb_spin} AEMET API ({cli::pb_current}/{cli::pb_total}) ", + "| {cli::pb_bar} {cli::pb_percent} ", + "| ETA:{cli::pb_eta} [{cli::pb_elapsed}]" + ), + total = length(station), clear = FALSE + ) + } + + # nocov end + # nolint end + + for (id in station) { + apidest <- paste0("/api/valores/climatologicos/normales/estacion/", id) + + if (progress) cli::cli_progress_update() # nocov + df <- get_data_aemet(apidest = apidest, verbose = verbose) + + final_result <- c(final_result, list(df)) + } + + + # nolint start + # nocov start + if (progress) { + cli::cli_progress_done() + options( + cli.progress_bar_style = opts$cli.progress_bar_style, + cli.progress_show_after = opts$cli.progress_show_after, + cli.spinner = opts$cli.spinner + ) } - final_result <- - aemet_hlp_guess(final_result, "indicativo", dec_mark = ".") + # nocov end + # nolint end + + final_result <- dplyr::bind_rows(final_result) + final_result <- dplyr::as_tibble(final_result) + final_result <- dplyr::distinct(final_result) + final_result <- aemet_hlp_guess(final_result, "indicativo", dec_mark = ".") # Check spatial---- if (return_sf) { # Coordinates from statios - sf_stations <- - aemet_stations(verbose, return_sf = FALSE) - sf_stations <- - sf_stations[c("indicativo", "latitud", "longitud")] + sf_stations <- aemet_stations(verbose, return_sf = FALSE) + sf_stations <- sf_stations[c("indicativo", "latitud", "longitud")] - final_result <- dplyr::left_join(final_result, - sf_stations, + final_result <- dplyr::left_join(final_result, sf_stations, by = "indicativo" ) - final_result <- - aemet_hlp_sf(final_result, "latitud", "longitud", verbose) - } + final_result <- aemet_hlp_sf(final_result, "latitud", "longitud", verbose) + } return(final_result) } @@ -103,22 +139,23 @@ aemet_normal_clim <- function(station = NULL, verbose = FALSE, #' #' @export aemet_normal_clim_all <- function(verbose = FALSE, return_sf = FALSE, - extract_metadata = FALSE) { + extract_metadata = FALSE, progress = TRUE) { # Parameters are validated on aemet_normal_clim if (isTRUE(extract_metadata)) { stations <- data.frame(indicativo = default_station) } else { - stations <- aemet_stations(verbose = verbose) + stations <- aemet_stations(verbose = verbose) # nocov } - data_all <- - aemet_normal_clim( - stations$indicativo, - verbose = verbose, - return_sf = return_sf, - extract_metadata = extract_metadata - ) + # No cover since is a huge extraction + # nocov start + data_all <- aemet_normal_clim(stations$indicativo, + verbose = verbose, + return_sf = return_sf, extract_metadata = extract_metadata, + progress = progress + ) + # nocov end return(data_all) } diff --git a/R/aemet_stations.R b/R/aemet_stations.R index 95a411f5..7aa2444f 100644 --- a/R/aemet_stations.R +++ b/R/aemet_stations.R @@ -7,13 +7,13 @@ #' #' @family aemet_api_data #' -#' @note Code modified from project +#' @note Code modified from project . #' #' @inheritParams aemet_daily_clim #' #' @inheritParams aemet_last_obs #' -#' @return A [`tibble`][tibble::tibble()] or a \CRANpkg{sf} object +#' @return A [`tibble`][tibble::tibble()] or a \CRANpkg{sf} object. #' #' @inheritSection aemet_daily_clim API Key #' @@ -53,33 +53,26 @@ aemet_stations <- function(verbose = FALSE, return_sf = FALSE) { } } else { # Call API---- - stations <- - get_data_aemet( - apidest = paste0( - "/api/valores/climatologicos/", - "inventarioestaciones/todasestaciones" - ), - verbose = verbose - ) + stations <- get_data_aemet( + apidest = paste0( + "/api/valores/climatologicos/", + "inventarioestaciones/todasestaciones" + ), + verbose = verbose + ) # Formats---- stations$longitud <- dms2decdegrees(stations$longitud) stations$latitud <- dms2decdegrees(stations$latitud) - df <- stations[c( - "indicativo", - "indsinop", - "nombre", - "provincia", - "altitud", - "longitud", - "latitud" - )] + vnames <- c( + "indicativo", "indsinop", "nombre", "provincia", + "altitud", "longitud", "latitud" + ) + + df <- stations[vnames] - df <- aemet_hlp_guess(df, c( - "indicativo", - "indsinop" - )) + df <- aemet_hlp_guess(df, c("indicativo", "indsinop")) # Cache on temp dir saveRDS(df, cached_df) diff --git a/R/climaemet_news.R b/R/climaemet_news.R index 24d7b149..6221d3f5 100644 --- a/R/climaemet_news.R +++ b/R/climaemet_news.R @@ -16,6 +16,8 @@ #' } #' climaemet_news <- function() { + # nocov start file <- file.path(system.file(package = "climaemet"), "NEWS.md") file.show(file) + # nocov end } diff --git a/R/climatogram.R b/R/climatogram.R index c0160195..663271c2 100644 --- a/R/climatogram.R +++ b/R/climatogram.R @@ -1,3 +1,5 @@ +# nocov start + #' Walter & Lieth climatic diagram from normal climatology values #' #' @description @@ -8,8 +10,8 @@ #' @family aemet_plots #' @family climatogram #' -#' @param labels Character string as month labels for the X axis: "en" -#' (english), "es" (spanish), "fr" (french), etc. +#' @param labels Character string as month labels for the X axis: `"en"` +#' (english), `"es"` (spanish), `"fr"` (french), etc. #' #' @param ggplot2 `TRUE/FALSE`. On `TRUE` the function uses #' [ggclimat_walter_lieth()], if `FALSE` uses [`climatol::diagwl()`]. @@ -21,8 +23,8 @@ #' @inheritParams climatestripes_station #' #' @inheritSection aemet_daily_clim API Key - -#' @note The code is based on code from the CRAN package \CRANpkg{climatol} +#' @note +#' The code is based on code from the CRAN package \CRANpkg{climatol}. #' #' @references #' - Walter, H. K., Harnickell, E., Lieth, F. H. H., & Rehder, H. (1967). @@ -114,7 +116,7 @@ climatogram_normal <- function(station, labels = "en", verbose = FALSE, #' @inheritParams climatogram_normal #' @inheritParams aemet_monthly_period #' -#' @note The code is based on code from the CRAN package \CRANpkg{climatol} +#' @note The code is based on code from the CRAN package \CRANpkg{climatol}. #' #' @references #' - Walter, H. K., Harnickell, E., Lieth, F. H. H., & Rehder, H. (1967). @@ -137,8 +139,6 @@ climatogram_normal <- function(station, labels = "en", verbose = FALSE, climatogram_period <- function(station = NULL, start = 1990, end = 2020, labels = "en", verbose = FALSE, ggplot2 = TRUE, ...) { - message("Data download may take a few minutes ... please wait \n") - data_raw <- aemet_monthly_period(station, start = start, end = end, @@ -157,7 +157,7 @@ climatogram_period <- function(station = NULL, start = 1990, end = 2020, gsub("\\s*\\([^\\)]+\\)", "", as.character(data$ta_min)) ) - data$fecha <- as.Date(paste0(data$fecha, "-01")) + data$fecha <- as.Date(paste0(data$fecha, "-01"), format = "%Y-%m-%d") data$mes <- as.integer(format(data$fecha, "%m")) data <- data[names(data) != "fecha"] data <- tibble::as_tibble(aggregate(. ~ mes, data, mean)) @@ -198,13 +198,10 @@ climatogram_period <- function(station = NULL, start = 1990, end = 2020, stop("\n\npackage climatol required, please install it first") } - climatol::diagwl( - data, + climatol::diagwl(data, est = stations$nombre, - alt = stations$altitud, - per = paste(start, "-", end), - mlab = labels, - ... + alt = stations$altitud, per = paste(start, "-", end), + mlab = labels, cols = NULL, ... ) } } @@ -227,15 +224,15 @@ climatogram_period <- function(station = NULL, start = 1990, end = 2020, #' #' @param dat Monthly climatic data for which the diagram will be plotted. #' -#' @param est Name of the climatological station +#' @param est Name of the climatological station. #' -#' @param alt Altitude of the climatological station +#' @param alt Altitude of the climatological station. #' -#' @param per Period on which the averages have been computed -#' @param mlab Month labels for the X axis. Use 2-digit language code ("en", -#' "es", etc.). See [`readr::locale()`] for info. -#' @param pcol Color pen for precipitation. -#' @param tcol Color pen for temperature. +#' @param per Period on which the averages have been computed. +#' @param mlab Month labels for the X axis. Use 2-digit language code (`"en"`, +#' `"es"`, etc.). See [`readr::locale()`] for info. +#' @param pcol Color for precipitation. +#' @param tcol Color for temperature. #' @param pfcol Fill color for probable frosts. #' @param sfcol Fill color for sure frosts. #' @param shem Set to `TRUE` for southern hemisphere stations. @@ -777,3 +774,5 @@ ggclimat_walter_lieth <- function(dat, est = "", alt = NA, per = NA, return(wandlplot) } + +# nocov end diff --git a/R/codecov.yml b/R/codecov.yml new file mode 100644 index 00000000..3dff00fc --- /dev/null +++ b/R/codecov.yml @@ -0,0 +1,5 @@ +ignore: + - "R/stripes.R" + - "R/climatogram.R" + - "R/windrose.R" + diff --git a/R/stripes.R b/R/stripes.R index 0a083146..786d06bf 100644 --- a/R/stripes.R +++ b/R/stripes.R @@ -1,6 +1,8 @@ +# nocov start + #' Station climate stripes graph #' -#' Plot climate stripes graph for a station +#' Plot climate stripes graph for a station. #' #' @family aemet_plots #' @family stripes @@ -103,15 +105,15 @@ climatestripes_station <- function(station, start = 1950, end = 2020, #' possible and alert about risks of climate change. For more details see #' [ShowYourStripes](https://showyourstripes.info/). #' -#' @param data a data.frame with date(year) and temperature(temp) variables. +#' @param data a data.frame with date(`year`) and temperature(`temp`) variables. #' @param plot_type plot type (with labels, background, stripes with line -#' trend and animation). Accepted values are "background", "stripes", -#' "trend" or "animation". +#' trend and animation). Accepted values are `"background"`, `"stripes"`, +#' `"trend"` or `"animation"`. #' #' @param plot_title character string to be used for the graph title. #' #' @param n_temp Numeric value as the number of colors of the palette. -#' (default 11). +#' (default `11`). #' #' @param col_pal Character string indicating the name of the #' [hcl.pals()] color palette to be used for plotting. @@ -138,7 +140,6 @@ climatestripes_station <- function(station, start = 1950, end = 2020, #' labs(subtitle = "(1950-2020)") #' } #' @export - ggstripes <- function(data, plot_type = "stripes", plot_title = "", n_temp = 11, col_pal = "RdBu", ...) { if (!is.numeric(n_temp)) { @@ -441,3 +442,5 @@ ggstripes <- function(data, plot_type = "stripes", plot_title = "", # Clear environment except function rm(list = ls(all.names = TRUE)) } + +# nocov end diff --git a/R/utils.R b/R/utils.R index fa0dafb6..bd684383 100644 --- a/R/utils.R +++ b/R/utils.R @@ -6,26 +6,21 @@ #' @param preserve vector of names to preserve #' @return A [`tibble`][tibble::tibble()] #' @noRd -aemet_hlp_guess <- - function(tbl, - preserve = "", - dec_mark = ",", - group_mark = "") { - for (i in names(tbl)) { - if (class(tbl[[i]])[1] == "character" && !(i %in% preserve)) { - tbl[i] <- - readr::parse_guess( - tbl[[i]], - locale = readr::locale( - decimal_mark = dec_mark, - grouping_mark = group_mark - ), - na = "-" - ) - } +aemet_hlp_guess <- function(tbl, preserve = "", dec_mark = ",", + group_mark = "") { + for (i in names(tbl)) { + if (class(tbl[[i]])[1] == "character" && !(i %in% preserve)) { + tbl[i] <- readr::parse_guess(tbl[[i]], + locale = readr::locale( + decimal_mark = dec_mark, + grouping_mark = group_mark + ), + na = "-" + ) } - return(tbl) } + return(tbl) +} #' Convert to sf objects (maps) @@ -37,6 +32,7 @@ aemet_hlp_guess <- #' @noRd aemet_hlp_sf <- function(tbl, lat, lon, verbose = FALSE) { # Check if sf is installed + # nocov start if (!requireNamespace("sf", quietly = TRUE)) { message( "\n\npackage sf required for spatial conversion, ", @@ -45,7 +41,7 @@ aemet_hlp_sf <- function(tbl, lat, lon, verbose = FALSE) { message("\nReturnig a tibble") return(tbl) } - + # nocov end if (lat %in% names(tbl) && lon %in% names(tbl)) { if (any(is.na(tbl[[lat]])) || any(is.na(tbl[[lon]]))) { message("Found NA coordinates. Returning a tibble") @@ -57,11 +53,7 @@ aemet_hlp_sf <- function(tbl, lat, lon, verbose = FALSE) { } - out <- - sf::st_as_sf(tbl, - coords = c(lon, lat), - crs = sf::st_crs(4326) - ) + out <- sf::st_as_sf(tbl, coords = c(lon, lat), crs = sf::st_crs(4326)) if (verbose) { message("spatial conversion succesful") } diff --git a/R/windrose.R b/R/windrose.R index 6622b4a3..aceeb826 100644 --- a/R/windrose.R +++ b/R/windrose.R @@ -1,3 +1,5 @@ +# nocov start + #' Windrose (speed/direction) diagram of a station over a days period #' #' @description @@ -7,8 +9,8 @@ #' @family aemet_plots #' @family wind #' -#' @param start Character string as start date (format: YYYY-MM-DD). -#' @param end Character string as end date (format: YYYY-MM-DD). +#' @param start Character string as start date (format: `"YYYY-MM-DD"`). +#' @param end Character string as end date (format: `"YYYY-MM-DD"`). #' #' @inheritSection aemet_daily_clim API Key #' @@ -18,7 +20,7 @@ #' #' @seealso [aemet_daily_clim()] #' -#' @return A \CRANpkg{ggplot2} object +#' @return A \CRANpkg{ggplot2} object. #' #' #' @examplesIf aemet_detect_api_key() @@ -92,8 +94,8 @@ windrose_days <- function(station, start = "2000-12-01", end = "2000-12-31", #' @family aemet_plots #' @family wind #' -#' @param start Numeric value as start year (format: YYYY). -#' @param end Numeric value as end year (format: YYYY). +#' @param start Numeric value as start year (format: `YYYY`). +#' @param end Numeric value as end year (format: `YYYY`). #' #' @inheritParams windrose_days #' @@ -179,13 +181,13 @@ windrose_period <- function(station, start = 2000, end = 2010, n_directions = 8, #' @param facet Character or factor vector of the facets used to plot the #' various windroses. #' @param n_directions Numeric value as the number of direction bins to plot -#' (petals on the rose). The number of directions defaults to 8. +#' (petals on the rose). The number of directions defaults to `8`. #' @param n_speeds Numeric value as the number of equally spaced wind speed -#' bins to plot. This is used if `speed_cuts` is `NA` (default 5). +#' bins to plot. This is used if `speed_cuts` is `NA` (default `5`). #' @param speed_cuts Numeric vector containing the cut points for the wind #' speed intervals, or `NA` (default). #' @param calm_wind Numeric value as the upper limit for wind speed that is -#' considered calm (default 0). +#' considered calm (default `0`). #' @param legend_title Character string to be used for the legend title. #' @param plot_title Character string to be used for the plot title. #' @param col_pal Character string indicating the name of the @@ -196,7 +198,7 @@ windrose_period <- function(station, start = 2000, end = 2010, n_directions = 8, #' @seealso [ggplot2::theme()] for more possible arguments to pass to #' `ggwindrose`. #' -#' @return A \CRANpkg{ggplot2} object +#' @return A \CRANpkg{ggplot2} object`.` #' #' #' @examples @@ -412,3 +414,5 @@ ggwindrose <- function(speed, direction, n_directions = 8, n_speeds = 5, return(windrose_plot) } + +# nocov end diff --git a/README.Rmd b/README.Rmd index 4e8b905e..faf9f8ee 100644 --- a/README.Rmd +++ b/README.Rmd @@ -31,6 +31,8 @@ status](https://www.r-pkg.org/badges/version/climaemet)](https://CRAN.R-project. results](https://badges.cranchecks.info/worst/climaemet.svg)](https://cran.r-project.org/web/checks/check_results_climaemet.html) [![r-universe](https://ropenspain.r-universe.dev/badges/climaemet)](https://ropenspain.r-universe.dev/climaemet) [![R-CMD-check](https://github.com/rOpenSpain/climaemet/actions/workflows/roscron-check-full.yaml/badge.svg)](https://github.com/rOpenSpain/climaemet/actions/workflows/roscron-check-full.yaml) +[![R-hub](https://github.com/rOpenSpain/climaemet/actions/workflows/rhub.yaml/badge.svg)](https://github.com/rOpenSpain/climaemet/actions/workflows/rhub.yaml) +[![codecov](https://codecov.io/gh/rOpenSpain/climaemet/graph/badge.svg?token=ZD3FL138Z4)](https://app.codecov.io/gh/rOpenSpain/climaemet) [![DOI](https://img.shields.io/badge/DOI-10.5281/zenodo.5205573-blue)](https://doi.org/10.5281/zenodo.5205573) [![metacran downloads](https://cranlogs.r-pkg.org/badges/climaemet)](https://cran.r-project.org/package=climaemet) diff --git a/README.md b/README.md index 6c38c15c..1e2c6d1c 100644 --- a/README.md +++ b/README.md @@ -14,6 +14,8 @@ status](https://www.r-pkg.org/badges/version/climaemet)](https://CRAN.R-project. results](https://badges.cranchecks.info/worst/climaemet.svg)](https://cran.r-project.org/web/checks/check_results_climaemet.html) [![r-universe](https://ropenspain.r-universe.dev/badges/climaemet)](https://ropenspain.r-universe.dev/climaemet) [![R-CMD-check](https://github.com/rOpenSpain/climaemet/actions/workflows/roscron-check-full.yaml/badge.svg)](https://github.com/rOpenSpain/climaemet/actions/workflows/roscron-check-full.yaml) +[![R-hub](https://github.com/rOpenSpain/climaemet/actions/workflows/rhub.yaml/badge.svg)](https://github.com/rOpenSpain/climaemet/actions/workflows/rhub.yaml) +[![codecov](https://codecov.io/gh/rOpenSpain/climaemet/graph/badge.svg?token=ZD3FL138Z4)](https://app.codecov.io/gh/rOpenSpain/climaemet) [![DOI](https://img.shields.io/badge/DOI-10.5281/zenodo.5205573-blue)](https://doi.org/10.5281/zenodo.5205573) [![metacran downloads](https://cranlogs.r-pkg.org/badges/climaemet)](https://cran.r-project.org/package=climaemet) @@ -117,71 +119,22 @@ library(climaemet) # See a tibble in action aemet_last_obs("9434") -#> HTTP 429: Límite de peticiones o caudal por minuto excedido para este usuario. Espere al siguiente minuto. Retrying... -#> Waiting 7s for retry backoff ■■■■■■ Waiting 7s for retry backoff ■■■■■■■ -#> Waiting 7s for retry backoff ■■■■■■■■ Waiting 7s for retry backoff ■■■■■■■■■ -#> Waiting 7s for retry backoff ■■■■■■■■■■ Waiting 7s for retry backoff -#> ■■■■■■■■■■■ Waiting 7s for retry backoff ■■■■■■■■■■■■ Waiting 7s for retry -#> backoff ■■■■■■■■■■■■■ Waiting 7s for retry backoff ■■■■■■■■■■■■■■ Waiting 7s -#> for retry backoff ■■■■■■■■■■■■■■■ Waiting 7s for retry backoff ■■■■■■■■■■■■■■■■ -#> Waiting 7s for retry backoff ■■■■■■■■■■■■■■■■■ Waiting 7s for retry backoff -#> ■■■■■■■■■■■■■■■■■■ Waiting 7s for retry backoff ■■■■■■■■■■■■■■■■■■■ Waiting 7s -#> for retry backoff ■■■■■■■■■■■■■■■■■■■■ Waiting 7s for retry backoff -#> ■■■■■■■■■■■■■■■■■■■■■ Waiting 7s for retry backoff ■■■■■■■■■■■■■■■■■■■■■■ -#> Waiting 7s for retry backoff ■■■■■■■■■■■■■■■■■■■■■■■ Waiting 7s for retry -#> backoff ■■■■■■■■■■■■■■■■■■■■■■■■ Waiting 7s for retry backoff -#> ■■■■■■■■■■■■■■■■■■■■■■■■■ Waiting 7s for retry backoff -#> ■■■■■■■■■■■■■■■■■■■■■■■■■■ Waiting 7s for retry backoff -#> ■■■■■■■■■■■■■■■■■■■■■■■■■■■ Waiting 7s for retry backoff -#> ■■■■■■■■■■■■■■■■■■■■■■■■■■■■ Waiting 7s for retry backoff -#> ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ Waiting 7s for retry backoff -#> ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ Waiting 11s for retry backoff ■■■■ Waiting 11s -#> for retry backoff ■■■■■ Waiting 11s for retry backoff ■■■■■ Waiting 11s for -#> retry backoff ■■■■■ Waiting 11s for retry backoff ■■■■■■ Waiting 11s for retry -#> backoff ■■■■■■■ Waiting 11s for retry backoff ■■■■■■■ Waiting 11s for retry -#> backoff ■■■■■■■■ Waiting 11s for retry backoff ■■■■■■■■■ Waiting 11s for retry -#> backoff ■■■■■■■■■ Waiting 11s for retry backoff ■■■■■■■■■■ Waiting 11s for -#> retry backoff ■■■■■■■■■■ Waiting 11s for retry backoff ■■■■■■■■■■■ Waiting 11s -#> for retry backoff ■■■■■■■■■■■ Waiting 11s for retry backoff ■■■■■■■■■■■■ -#> Waiting 11s for retry backoff ■■■■■■■■■■■■■ Waiting 11s for retry backoff -#> ■■■■■■■■■■■■■ Waiting 11s for retry backoff ■■■■■■■■■■■■■■ Waiting 11s for -#> retry backoff ■■■■■■■■■■■■■■ Waiting 11s for retry backoff ■■■■■■■■■■■■■■■ -#> Waiting 11s for retry backoff ■■■■■■■■■■■■■■■■ Waiting 11s for retry backoff -#> ■■■■■■■■■■■■■■■■ Waiting 11s for retry backoff ■■■■■■■■■■■■■■■■■ Waiting 11s -#> for retry backoff ■■■■■■■■■■■■■■■■■ Waiting 11s for retry backoff -#> ■■■■■■■■■■■■■■■■■■ Waiting 11s for retry backoff ■■■■■■■■■■■■■■■■■■ Waiting 11s -#> for retry backoff ■■■■■■■■■■■■■■■■■■■ Waiting 11s for retry backoff -#> ■■■■■■■■■■■■■■■■■■■■ Waiting 11s for retry backoff ■■■■■■■■■■■■■■■■■■■■ Waiting -#> 11s for retry backoff ■■■■■■■■■■■■■■■■■■■■■ Waiting 11s for retry backoff -#> ■■■■■■■■■■■■■■■■■■■■■■ Waiting 11s for retry backoff ■■■■■■■■■■■■■■■■■■■■■■ -#> Waiting 11s for retry backoff ■■■■■■■■■■■■■■■■■■■■■■■ Waiting 11s for retry -#> backoff ■■■■■■■■■■■■■■■■■■■■■■■ Waiting 11s for retry backoff -#> ■■■■■■■■■■■■■■■■■■■■■■■■ Waiting 11s for retry backoff ■■■■■■■■■■■■■■■■■■■■■■■■ -#> Waiting 11s for retry backoff ■■■■■■■■■■■■■■■■■■■■■■■■■ Waiting 11s for retry -#> backoff ■■■■■■■■■■■■■■■■■■■■■■■■■■ Waiting 11s for retry backoff -#> ■■■■■■■■■■■■■■■■■■■■■■■■■■ Waiting 11s for retry backoff -#> ■■■■■■■■■■■■■■■■■■■■■■■■■■■ Waiting 11s for retry backoff -#> ■■■■■■■■■■■■■■■■■■■■■■■■■■■ Waiting 11s for retry backoff -#> ■■■■■■■■■■■■■■■■■■■■■■■■■■■■ Waiting 11s for retry backoff -#> ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ Waiting 11s for retry backoff -#> ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ Waiting 11s for retry backoff -#> ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ Waiting 11s for retry backoff -#> ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ -#> # A tibble: 12 × 25 +#> # A tibble: 13 × 25 #> idema lon fint prec alt vmax vv dv lat dmax #> -#> 1 9434 -1.00 2024-06-19 22:00:00 0 249 14.1 8.8 307 41.7 318 -#> 2 9434 -1.00 2024-06-19 23:00:00 0 249 14.5 7.3 300 41.7 293 -#> 3 9434 -1.00 2024-06-20 00:00:00 0 249 9.4 3.9 316 41.7 293 -#> 4 9434 -1.00 2024-06-20 01:00:00 0 249 8.4 5.9 310 41.7 295 -#> 5 9434 -1.00 2024-06-20 02:00:00 0 249 8.4 6.1 309 41.7 323 -#> 6 9434 -1.00 2024-06-20 03:00:00 0 249 10 7.7 298 41.7 298 -#> 7 9434 -1.00 2024-06-20 04:00:00 0 249 10.4 7.2 304 41.7 325 -#> 8 9434 -1.00 2024-06-20 05:00:00 0 249 9.7 6.5 301 41.7 313 -#> 9 9434 -1.00 2024-06-20 06:00:00 4 249 9.2 4.5 304 41.7 305 -#> 10 9434 -1.00 2024-06-20 07:00:00 0 249 9.8 6.9 291 41.7 280 -#> 11 9434 -1.00 2024-06-20 08:00:00 0 249 11 5.1 313 41.7 308 -#> 12 9434 -1.00 2024-06-20 09:00:00 0 249 7.9 4.9 320 41.7 308 +#> 1 9434 -1.00 2024-06-21 19:00:00 0 249 8.2 2.7 339 41.7 300 +#> 2 9434 -1.00 2024-06-21 20:00:00 0 249 4.8 0.7 8 41.7 358 +#> 3 9434 -1.00 2024-06-21 21:00:00 0 249 3.5 2.1 321 41.7 330 +#> 4 9434 -1.00 2024-06-21 22:00:00 0 249 4.6 3.6 264 41.7 263 +#> 5 9434 -1.00 2024-06-21 23:00:00 0 249 4.1 3 257 41.7 270 +#> 6 9434 -1.00 2024-06-22 00:00:00 0 249 4.7 2.3 262 41.7 288 +#> 7 9434 -1.00 2024-06-22 01:00:00 0 249 4.3 2.6 315 41.7 240 +#> 8 9434 -1.00 2024-06-22 02:00:00 0 249 6.2 5 292 41.7 298 +#> 9 9434 -1.00 2024-06-22 03:00:00 0 249 6.8 4.4 296 41.7 288 +#> 10 9434 -1.00 2024-06-22 04:00:00 0 249 5.5 3.5 305 41.7 293 +#> 11 9434 -1.00 2024-06-22 05:00:00 0 249 5.6 2.5 302 41.7 310 +#> 12 9434 -1.00 2024-06-22 06:00:00 0 249 5.5 4.3 312 41.7 315 +#> 13 9434 -1.00 2024-06-22 07:00:00 0 249 7.2 4.9 302 41.7 303 #> # ℹ 15 more variables: ubi , pres , hr , stdvv , ts , #> # pres_nmar , tamin , ta , tamax , tpr , #> # stddv , inso , tss5cm , pacutp , tss20cm @@ -220,12 +173,12 @@ knitr::kable(head(data_observation)) | idema | lon | fint | prec | alt | vmax | vv | dv | lat | dmax | ubi | pres | hr | stdvv | ts | pres_nmar | tamin | ta | tamax | tpr | stddv | inso | tss5cm | pacutp | tss20cm | |:------|----------:|:--------------------|-----:|----:|-----:|----:|----:|---------:|-----:|:--------------------|------:|----:|------:|-----:|----------:|------:|-----:|------:|-----:|------:|-----:|-------:|-------:|--------:| -| 9434 | -1.004167 | 2024-06-19 22:00:00 | 0 | 249 | 14.1 | 8.8 | 307 | 41.66056 | 318 | ZARAGOZA AEROPUERTO | 984.3 | 61 | 1.1 | 21.6 | 1013.4 | 20.6 | 20.7 | 23.9 | 13.0 | 9 | 0 | 32.9 | 0 | 33.7 | -| 9434 | -1.004167 | 2024-06-19 23:00:00 | 0 | 249 | 14.5 | 7.3 | 300 | 41.66056 | 293 | ZARAGOZA AEROPUERTO | 985.3 | 58 | 1.4 | 21.0 | 1014.5 | 20.2 | 20.3 | 20.7 | 11.8 | 9 | 0 | 31.9 | 0 | 33.4 | -| 9434 | -1.004167 | 2024-06-20 00:00:00 | 0 | 249 | 9.4 | 3.9 | 316 | 41.66056 | 293 | ZARAGOZA AEROPUERTO | 984.9 | 60 | 0.8 | 19.6 | 1014.2 | 19.4 | 19.4 | 20.4 | 11.4 | 10 | 0 | 31.1 | 0 | 33.0 | -| 9434 | -1.004167 | 2024-06-20 01:00:00 | 0 | 249 | 8.4 | 5.9 | 310 | 41.66056 | 295 | ZARAGOZA AEROPUERTO | 984.8 | 60 | 0.8 | 19.5 | 1014.1 | 19.0 | 19.0 | 19.4 | 11.1 | 7 | 0 | 30.3 | 0 | 32.6 | -| 9434 | -1.004167 | 2024-06-20 02:00:00 | 0 | 249 | 8.4 | 6.1 | 309 | 41.66056 | 323 | ZARAGOZA AEROPUERTO | 984.3 | 61 | 0.9 | 19.9 | 1013.6 | 18.6 | 18.7 | 19.1 | 11.0 | 7 | 0 | 29.7 | 0 | 32.2 | -| 9434 | -1.004167 | 2024-06-20 03:00:00 | 0 | 249 | 10.0 | 7.7 | 298 | 41.66056 | 298 | ZARAGOZA AEROPUERTO | 984.4 | 63 | 0.8 | 19.9 | 1013.7 | 18.4 | 18.8 | 18.8 | 11.6 | 6 | 0 | 29.3 | 0 | 31.8 | +| 9434 | -1.004167 | 2024-06-21 19:00:00 | 0 | 249 | 8.2 | 2.7 | 339 | 41.66056 | 300 | ZARAGOZA AEROPUERTO | 990.0 | 40 | 0.7 | 25.5 | 1018.8 | 25.6 | 25.6 | 26.7 | 11.0 | 15 | 60.0 | 31.7 | 0 | 29.4 | +| 9434 | -1.004167 | 2024-06-21 20:00:00 | 0 | 249 | 4.8 | 0.7 | 8 | 41.66056 | 358 | ZARAGOZA AEROPUERTO | 990.5 | 46 | 0.2 | 21.8 | 1019.5 | 23.4 | 23.4 | 25.6 | 11.1 | 27 | 17.7 | 30.2 | 0 | 29.6 | +| 9434 | -1.004167 | 2024-06-21 21:00:00 | 0 | 249 | 3.5 | 2.1 | 321 | 41.66056 | 330 | ZARAGOZA AEROPUERTO | 991.3 | 45 | 0.4 | 21.8 | 1020.4 | 23.2 | 23.2 | 23.5 | 10.6 | 10 | 0.0 | 29.0 | 0 | 29.5 | +| 9434 | -1.004167 | 2024-06-21 22:00:00 | 0 | 249 | 4.6 | 3.6 | 264 | 41.66056 | 263 | ZARAGOZA AEROPUERTO | 991.8 | 53 | 0.4 | 21.0 | 1021.1 | 21.1 | 21.1 | 23.2 | 11.1 | 6 | 0.0 | 28.0 | 0 | 29.4 | +| 9434 | -1.004167 | 2024-06-21 23:00:00 | 0 | 249 | 4.1 | 3.0 | 257 | 41.66056 | 270 | ZARAGOZA AEROPUERTO | 991.8 | 54 | 0.3 | 20.1 | 1021.2 | 20.6 | 20.6 | 21.2 | 11.0 | 6 | 0.0 | 27.2 | 0 | 29.1 | +| 9434 | -1.004167 | 2024-06-22 00:00:00 | 0 | 249 | 4.7 | 2.3 | 262 | 41.66056 | 288 | ZARAGOZA AEROPUERTO | 991.8 | 55 | 0.4 | 18.7 | 1021.2 | 19.8 | 19.8 | 20.6 | 10.5 | 11 | 0.0 | 26.5 | 0 | 28.8 | ``` r @@ -252,14 +205,14 @@ data_monthly <- aemet_monthly_clim(station, year = 2022) knitr::kable(head(data_monthly)) ``` -| fecha | indicativo | p_max | n_cub | hr | n_gra | n_fog | inso | q_max | nw_55 | q_mar | q_med | tm_min | ta_max | ts_min | nt_30 | nv_0050 | n_des | w_racha | np_100 | n_nub | p_sol | nw_91 | np_001 | ta_min | w_rec | e | np_300 | nv_1000 | p_mes | n_llu | n_tor | w_med | nt_00 | ti_max | n_nie | tm_mes | tm_max | nv_0100 | q_min | np_010 | evap | -|:--------|:-----------|:-------------|------:|----:|------:|------:|-----:|:---------------|------:|-------:|------:|-------:|:-------------|-------:|------:|--------:|------:|:----------------|-------:|------:|------:|------:|-------:|:-------------|------:|----:|-------:|--------:|------:|------:|------:|------:|------:|-------:|------:|-------:|-------:|--------:|:--------------|-------:|-----:| -| 2022-10 | 9434 | 1.4(16) | 9 | 63 | 0 | 1 | 5.9 | 998.8(06) | 1 | 1019.3 | 989.4 | 14.9 | 29.6(16) | 18.4 | 0 | 0 | 6 | 26/18.6(19) | 0 | 16 | 53 | 0 | 7 | 10.5(01) | 245 | 147 | 0 | 0 | 6.2 | 11 | 1 | 10 | 0 | 20.8 | 0 | 20.3 | 25.6 | 0 | 981.8(15) | 4 | NA | -| 2022-11 | 9434 | 6.2(03) | 7 | 71 | 1 | 3 | 4.6 | 1000.0(26) | 7 | 1018.5 | 987.8 | 8.2 | 24.1(01) | 12.9 | 0 | 0 | 3 | 35/23.9(21) | 0 | 20 | 46 | 0 | 14 | 2.8(27) | 319 | 107 | 0 | 2 | 29.8 | 15 | 0 | 14 | 0 | 11.5 | 0 | 12.8 | 17.2 | 0 | 973.4(17) | 6 | 1165 | -| 2022-12 | 9434 | 19.0(13) | 14 | 82 | 0 | 14 | 4.0 | 1001.5(27) | 2 | 1016.5 | 985.5 | 5.4 | 18.9(30) | 11.6 | 0 | 0 | 0 | 29/17.8(10) | 1 | 16 | 44 | 0 | 8 | 1.5(03) | 235 | 96 | 0 | 8 | 35.6 | 12 | 0 | 10 | 0 | 5.1 | 0 | 9.2 | 13.0 | 0 | 967.1(15) | 5 | 673 | -| 2022-13 | 9434 | 25.4(24/ago) | 76 | 57 | 3 | 23 | 8.1 | 1005.7(29/ene) | 76 | 1017.8 | 987.7 | 12.0 | 41.9(17/jul) | 24.8 | 107 | 0 | 94 | 30/30.8(24/ago) | 3 | 194 | 65 | 1 | 72 | -3.2(23/ene) | 360 | 114 | 0 | 14 | 214.2 | 92 | 17 | 15 | 16 | 5.1 | 0 | 17.6 | 23.2 | 0 | 965.4(23/abr) | 44 | NA | -| 2022-1 | 9434 | 7.0(04) | 4 | 68 | 0 | 3 | 7.6 | 1005.7(29) | 7 | 1028.5 | 996.7 | 1.0 | 17.2(04) | 11.2 | 0 | 0 | 21 | 31/24.2(31) | 0 | 6 | 79 | 0 | 2 | -3.2(23) | 353 | 65 | 0 | 3 | 7.4 | 4 | 0 | 15 | 16 | 5.8 | 0 | 6.3 | 11.6 | 0 | 976.6(04) | 1 | 1021 | -| 2022-2 | 9434 | 0.4(13) | 2 | 57 | 0 | 2 | 7.8 | 1002.2(08) | 9 | 1025.4 | 994.3 | 5.0 | 20.5(02) | 9.3 | 0 | 0 | 7 | 30/23.9(01) | 0 | 19 | 74 | 0 | 2 | 0.3(10) | 408 | 73 | 0 | 0 | 0.8 | 4 | 0 | 17 | 0 | 12.4 | 0 | 10.4 | 15.8 | 0 | 982.3(14) | 0 | 1632 | +| fecha | indicativo | p_max | n_cub | hr | n_gra | n_fog | inso | q_max | nw_55 | q_mar | q_med | tm_min | ta_max | ts_min | nt_30 | nv_0050 | n_des | w_racha | np_100 | n_nub | p_sol | nw_91 | np_001 | ta_min | w_rec | e | np_300 | nv_1000 | p_mes | n_llu | n_tor | w_med | nt_00 | ti_max | n_nie | tm_mes | tm_max | nv_0100 | q_min | np_010 | evap | +|:--------|:-----------|:---------|------:|----:|------:|------:|-----:|:-----------|------:|-------:|------:|-------:|:---------|-------:|------:|--------:|------:|:------------|-------:|------:|------:|------:|-------:|:---------|------:|----:|-------:|--------:|------:|------:|------:|------:|------:|-------:|------:|-------:|-------:|--------:|:----------|-------:|-----:| +| 2022-01 | 9434 | 7.0(04) | 4 | 68 | 0 | 3 | 7.6 | 1005.7(29) | 7 | 1028.5 | 996.7 | 1.0 | 17.2(04) | 11.2 | 0 | 0 | 21 | 31/24.2(31) | 0 | 6 | 79 | 0 | 2 | -3.2(23) | 353 | 65 | 0 | 3 | 7.4 | 4 | 0 | 15 | 16 | 5.8 | 0 | 6.3 | 11.6 | 0 | 976.6(04) | 1 | 1021 | +| 2022-02 | 9434 | 0.4(13) | 2 | 57 | 0 | 2 | 7.8 | 1002.2(08) | 9 | 1025.4 | 994.3 | 5.0 | 20.5(02) | 9.3 | 0 | 0 | 7 | 30/23.9(01) | 0 | 19 | 74 | 0 | 2 | 0.3(10) | 408 | 73 | 0 | 0 | 0.8 | 4 | 0 | 17 | 0 | 12.4 | 0 | 10.4 | 15.8 | 0 | 982.3(14) | 0 | 1632 | +| 2022-03 | 9434 | 6.2(11) | 19 | 69 | 0 | 0 | 3.8 | 997.2(22) | 7 | 1019.3 | 988.4 | 7.4 | 19.5(01) | 11.8 | 0 | 0 | 0 | 31/18.6(17) | 0 | 12 | 32 | 0 | 13 | 3.0(09) | 388 | 92 | 0 | 0 | 33.6 | 13 | 1 | 16 | 0 | 10.5 | 0 | 11.1 | 14.8 | 0 | 971.2(30) | 8 | 1367 | +| 2022-04 | 9434 | 11.8(27) | 9 | 56 | 0 | 0 | 8.5 | 996.0(29) | 9 | 1014.1 | 983.9 | 8.8 | 25.8(16) | 14.2 | 0 | 0 | 5 | 28/22.2(08) | 1 | 16 | 64 | 0 | 9 | 0.5(04) | 469 | 95 | 0 | 0 | 31.0 | 11 | 0 | 20 | 0 | 10.2 | 0 | 14.1 | 19.3 | 0 | 965.4(23) | 7 | 2357 | +| 2022-05 | 9434 | 5.6(03) | 6 | 45 | 0 | 0 | 10.7 | 994.8(26) | 5 | 1016.2 | 986.6 | 14.8 | 35.3(21) | 19.9 | 14 | 0 | 11 | 31/19.2(26) | 0 | 14 | 74 | 0 | 5 | 11.3(03) | 399 | 118 | 0 | 0 | 13.8 | 5 | 2 | 18 | 0 | 18.3 | 0 | 21.6 | 28.2 | 0 | 972.7(29) | 4 | 3486 | +| 2022-06 | 9434 | 6.4(16) | 0 | 38 | 0 | 0 | 11.5 | 992.3(12) | 12 | 1013.1 | 984.1 | 19.5 | 41.2(15) | 24.0 | 26 | 0 | 6 | 28/22.5(11) | 0 | 24 | 76 | 0 | 4 | 14.4(28) | 383 | 132 | 0 | 0 | 9.4 | 5 | 5 | 16 | 0 | 24.8 | 0 | 26.7 | 33.9 | 0 | 975.2(19) | 3 | 3560 | ``` r diff --git a/codemeta.json b/codemeta.json index dd0feb25..8a849930 100644 --- a/codemeta.json +++ b/codemeta.json @@ -171,6 +171,19 @@ "url": "https://cran.r-project.org" }, "sameAs": "https://CRAN.R-project.org/package=sf" + }, + { + "@type": "SoftwareApplication", + "identifier": "testthat", + "name": "testthat", + "version": ">= 3.0.0", + "provider": { + "@id": "https://cran.r-project.org", + "@type": "Organization", + "name": "Comprehensive R Archive Network (CRAN)", + "url": "https://cran.r-project.org" + }, + "sameAs": "https://CRAN.R-project.org/package=testthat" } ], "softwareRequirements": { @@ -181,6 +194,19 @@ "version": ">= 3.6.0" }, "2": { + "@type": "SoftwareApplication", + "identifier": "cli", + "name": "cli", + "version": ">= 3.0.0", + "provider": { + "@id": "https://cran.r-project.org", + "@type": "Organization", + "name": "Comprehensive R Archive Network (CRAN)", + "url": "https://cran.r-project.org" + }, + "sameAs": "https://CRAN.R-project.org/package=cli" + }, + "3": { "@type": "SoftwareApplication", "identifier": "dplyr", "name": "dplyr", @@ -193,7 +219,7 @@ }, "sameAs": "https://CRAN.R-project.org/package=dplyr" }, - "3": { + "4": { "@type": "SoftwareApplication", "identifier": "ggplot2", "name": "ggplot2", @@ -206,7 +232,7 @@ }, "sameAs": "https://CRAN.R-project.org/package=ggplot2" }, - "4": { + "5": { "@type": "SoftwareApplication", "identifier": "httr2", "name": "httr2", @@ -219,7 +245,7 @@ }, "sameAs": "https://CRAN.R-project.org/package=httr2" }, - "5": { + "6": { "@type": "SoftwareApplication", "identifier": "jsonlite", "name": "jsonlite", @@ -232,7 +258,7 @@ }, "sameAs": "https://CRAN.R-project.org/package=jsonlite" }, - "6": { + "7": { "@type": "SoftwareApplication", "identifier": "rappdirs", "name": "rappdirs", @@ -245,7 +271,7 @@ }, "sameAs": "https://CRAN.R-project.org/package=rappdirs" }, - "7": { + "8": { "@type": "SoftwareApplication", "identifier": "readr", "name": "readr", @@ -258,7 +284,7 @@ }, "sameAs": "https://CRAN.R-project.org/package=readr" }, - "8": { + "9": { "@type": "SoftwareApplication", "identifier": "rlang", "name": "rlang", @@ -271,7 +297,7 @@ }, "sameAs": "https://CRAN.R-project.org/package=rlang" }, - "9": { + "10": { "@type": "SoftwareApplication", "identifier": "tibble", "name": "tibble", @@ -284,7 +310,7 @@ }, "sameAs": "https://CRAN.R-project.org/package=tibble" }, - "10": { + "11": { "@type": "SoftwareApplication", "identifier": "tidyr", "name": "tidyr", @@ -301,7 +327,7 @@ }, "applicationCategory": "Meteorology", "isPartOf": "https://ropenspain.es/", - "fileSize": "794.804KB", + "fileSize": "824.601KB", "citation": [ { "@type": "SoftwareSourceCode", @@ -332,7 +358,7 @@ ], "releaseNotes": "https://github.com/rOpenSpain/climaemet/blob/master/NEWS.md", "readme": "https://github.com/rOpenSpain/climaemet/blob/main/README.md", - "contIntegration": "https://github.com/rOpenSpain/climaemet/actions/workflows/roscron-check-full.yaml", + "contIntegration": ["https://github.com/rOpenSpain/climaemet/actions/workflows/roscron-check-full.yaml", "https://github.com/rOpenSpain/climaemet/actions/workflows/rhub.yaml", "https://app.codecov.io/gh/rOpenSpain/climaemet"], "developmentStatus": "https://www.repostatus.org/#active", "keywords": ["science", "data", "climate", "aemet", "r", "rstats", "cran", "r-package", "ropenspain", "forecast-api", "spain", "weather-api"] } diff --git a/data-raw/climaemet_9434_climatogram.R b/data-raw/climaemet_9434_climatogram.R index 35e78455..ea9aefe2 100644 --- a/data-raw/climaemet_9434_climatogram.R +++ b/data-raw/climaemet_9434_climatogram.R @@ -2,11 +2,9 @@ library(climaemet) -data_raw <- - aemet_normal_clim(9434, apikey = NULL, verbose = TRUE) +data_raw <- aemet_normal_clim(9434, verbose = TRUE) -data <- - data_raw[c("mes", "p_mes_md", "tm_max_md", "tm_min_md", "ta_min_min")] +data <- data_raw[c("mes", "p_mes_md", "tm_max_md", "tm_min_md", "ta_min_min")] data$mes <- as.numeric(data$mes) data <- data[data$mes < 13, ] diff --git a/data-raw/climaemet_9434_temp.R b/data-raw/climaemet_9434_temp.R index b3fa6d68..48e7d977 100644 --- a/data-raw/climaemet_9434_temp.R +++ b/data-raw/climaemet_9434_temp.R @@ -2,8 +2,7 @@ library(climaemet) -data_raw <- - aemet_monthly_period(9434, NULL, 1950, 2020, TRUE) +data_raw <- aemet_monthly_period(9434, 1950, 2020, TRUE) if (nrow(data_raw) == 0) stop("No valid results from the API") diff --git a/data/climaemet_9434_climatogram.rda b/data/climaemet_9434_climatogram.rda index 810a2b6f..a2f1b854 100644 Binary files a/data/climaemet_9434_climatogram.rda and b/data/climaemet_9434_climatogram.rda differ diff --git a/man/aemet_api_key.Rd b/man/aemet_api_key.Rd index 9b8dd054..64c653b7 100644 --- a/man/aemet_api_key.Rd +++ b/man/aemet_api_key.Rd @@ -9,10 +9,11 @@ aemet_api_key(apikey, overwrite = FALSE, install = FALSE) \arguments{ \item{apikey}{The API key provided to you from the AEMET formatted in quotes. A key can be acquired at -\url{https://opendata.aemet.es/centrodedescargas/inicio}.} +\url{https://opendata.aemet.es/centrodedescargas/inicio}. You can install +several API Keys as a vector of characters, see \strong{Details}.} \item{overwrite}{If this is set to \code{TRUE}, it will overwrite an existing -AEMET_API_KEY that you already have in local machine.} +\code{AEMET_API_KEY} that you already have in local machine.} \item{install}{if \code{TRUE}, will install the key in your local machine for use in future sessions. Defaults to \code{FALSE.}} @@ -22,17 +23,14 @@ None } \description{ This function will store your AEMET API key on your local machine so it can -be called securely without being stored in your code. After you have -installed your key, it can be called any time by typing -\code{Sys.getenv("AEMET_API_KEY")} and can be -used in package functions by simply typing \code{AEMET_API_KEY}. +be called securely without being stored in your code. Alternatively, you can install the API Key manually: \itemize{ \item Run \code{Sys.setenv(AEMET_API_KEY = "Your_Key")}. You would need to run this command on each session (Similar to \code{install = FALSE}). -\item Write this line on your .Renviron file: \code{AEMET_API_KEY = "Your_Key"} ( -same behavior than \code{install = TRUE}). This would store your API key +\item Write this line on your .Renviron file: \code{AEMET_API_KEY = "Your_Key"} +(same behavior than \code{install = TRUE}). This would store your API key permanently. } } diff --git a/man/aemet_daily.Rd b/man/aemet_daily.Rd index 8fb2d6c8..9c05c852 100644 --- a/man/aemet_daily.Rd +++ b/man/aemet_daily.Rd @@ -13,7 +13,8 @@ aemet_daily_clim( end = Sys.Date(), verbose = FALSE, return_sf = FALSE, - extract_metadata = FALSE + extract_metadata = FALSE, + progress = TRUE ) aemet_daily_period( @@ -22,7 +23,8 @@ aemet_daily_period( end = start, verbose = FALSE, return_sf = FALSE, - extract_metadata = FALSE + extract_metadata = FALSE, + progress = TRUE ) aemet_daily_period_all( @@ -30,14 +32,15 @@ aemet_daily_period_all( end = start, verbose = FALSE, return_sf = FALSE, - extract_metadata = FALSE + extract_metadata = FALSE, + progress = TRUE ) } \arguments{ \item{station}{Character string with station identifier code(s) (see \code{\link[=aemet_stations]{aemet_stations()}}) or "all" for all the stations.} -\item{start, end}{Character string with start and end date. See Details.} +\item{start, end}{Character string with start and end date. See \strong{Details}.} \item{verbose}{Logical \code{TRUE/FALSE}. Provides information about the flow of information between the client and server.} @@ -50,9 +53,12 @@ you need to have the \CRANpkg{sf} package installed.} \item{extract_metadata}{Logical \code{TRUE/FALSE}. On \code{TRUE} the output is a \code{\link[tibble:tibble]{tibble}} with the description of the fields. See also \code{\link[=get_metadata_aemet]{get_metadata_aemet()}}.} + +\item{progress}{Logical, display a \code{\link[cli:cli_progress_bar]{cli::cli_progress_bar()}} object. If +\code{verbose = TRUE} won't be displayed.} } \value{ -A \code{\link[tibble:tibble]{tibble}} or a \CRANpkg{sf} object +A \code{\link[tibble:tibble]{tibble}} or a \CRANpkg{sf} object. } \description{ Get climatology values for a station or for all the available stations. @@ -63,9 +69,9 @@ of \code{aemet_daily_clim()}. \code{start} and \code{end} parameters should be: \itemize{ \item For \code{aemet_daily_clim()}: A \code{Date} object or a string with format: -YYYY-MM-DD (2020-12-31) coercible with \code{\link[=as.Date]{as.Date()}}. +\code{YYYY-MM-DD} (\code{"2020-12-31"}) coercible with \code{\link[=as.Date]{as.Date()}}. \item For \code{aemet_daily_period()} and \code{aemet_daily_period_all()}: A string -representing the year(s) to be extracted: "2020", "2018". +representing the year(s) to be extracted: \code{"2020"}, \code{"2018"}. } } \section{API Key}{ diff --git a/man/aemet_detect_api_key.Rd b/man/aemet_detect_api_key.Rd index 7c206235..480d1329 100644 --- a/man/aemet_detect_api_key.Rd +++ b/man/aemet_detect_api_key.Rd @@ -2,15 +2,18 @@ % Please edit documentation in R/aemet_api_key.R \name{aemet_detect_api_key} \alias{aemet_detect_api_key} +\alias{aemet_show_api_key} \title{Check if an AEMET API Key is present for the current session} \usage{ aemet_detect_api_key(...) + +aemet_show_api_key(...) } \arguments{ \item{...}{Ignored} } \value{ -\code{TRUE} or \code{FALSE} +\code{TRUE} or \code{FALSE}. \code{aemet_show_api_key()} would display your stored API keys. } \description{ The function would detect if an API Key is available on this session: @@ -24,6 +27,11 @@ an API Key using \code{\link[=aemet_api_key]{aemet_api_key()}}, the latter would \examples{ aemet_detect_api_key() + +# CAUTION: This may reveal API Keys +if (FALSE) { + aemet_show_api_key() +} } \seealso{ Other aemet_auth: diff --git a/man/aemet_extremes_clim.Rd b/man/aemet_extremes_clim.Rd index fb1e55ab..9ff45f45 100644 --- a/man/aemet_extremes_clim.Rd +++ b/man/aemet_extremes_clim.Rd @@ -9,15 +9,16 @@ aemet_extremes_clim( parameter = "T", verbose = FALSE, return_sf = FALSE, - extract_metadata = FALSE + extract_metadata = FALSE, + progress = TRUE ) } \arguments{ \item{station}{Character string with station identifier code(s) -(see \code{\link[=aemet_stations]{aemet_stations()}})} +(see \code{\link[=aemet_stations]{aemet_stations()}}).} -\item{parameter}{Character string as temperature ("T"), -precipitation ("P") or wind ("V") parameter.} +\item{parameter}{Character string as temperature (\code{"T"}), +precipitation (\code{"P"}) or wind (\code{"V"}) parameter.} \item{verbose}{Logical \code{TRUE/FALSE}. Provides information about the flow of information between the client and server.} @@ -30,9 +31,13 @@ you need to have the \CRANpkg{sf} package installed.} \item{extract_metadata}{Logical \code{TRUE/FALSE}. On \code{TRUE} the output is a \code{\link[tibble:tibble]{tibble}} with the description of the fields. See also \code{\link[=get_metadata_aemet]{get_metadata_aemet()}}.} + +\item{progress}{Logical, display a \code{\link[cli:cli_progress_bar]{cli::cli_progress_bar()}} object. If +\code{verbose = TRUE} won't be displayed.} } \value{ -A \code{\link[tibble:tibble]{tibble}} or a \CRANpkg{sf} object +A \code{\link[tibble:tibble]{tibble}} or a \CRANpkg{sf} object. If the function +finds an error when parsing it would return the result as a \code{list()} object. } \description{ Get recorded extreme values for a station. diff --git a/man/aemet_forecast.Rd b/man/aemet_forecast.Rd index 1d417fbc..8d737946 100644 --- a/man/aemet_forecast.Rd +++ b/man/aemet_forecast.Rd @@ -6,14 +6,24 @@ \alias{aemet_forecast_hourly} \title{Forecast database by municipality} \usage{ -aemet_forecast_daily(x, verbose = FALSE, extract_metadata = FALSE) - -aemet_forecast_hourly(x, verbose = FALSE, extract_metadata = FALSE) +aemet_forecast_daily( + x, + verbose = FALSE, + extract_metadata = FALSE, + progress = TRUE +) + +aemet_forecast_hourly( + x, + verbose = FALSE, + extract_metadata = FALSE, + progress = TRUE +) } \arguments{ \item{x}{A vector of municipality codes to extract. For convenience, \CRANpkg{climaemet} provides this data on the dataset \link{aemet_munic} -(see \code{municipio} field) as of January 2020.} +(see \code{municipio} field) as of January 2024.} \item{verbose}{Logical \code{TRUE/FALSE}. Provides information about the flow of information between the client and server.} @@ -21,6 +31,9 @@ information between the client and server.} \item{extract_metadata}{Logical \code{TRUE/FALSE}. On \code{TRUE} the output is a \code{\link[tibble:tibble]{tibble}} with the description of the fields. See also \code{\link[=get_metadata_aemet]{get_metadata_aemet()}}.} + +\item{progress}{Logical, display a \code{\link[cli:cli_progress_bar]{cli::cli_progress_bar()}} object. If +\code{verbose = TRUE} won't be displayed.} } \value{ A nested \code{\link[tibble:tibble]{tibble}}. Forecasted values can be @@ -113,7 +126,9 @@ ggplot(daily_temp_end) + \dontshow{\}) # examplesIf} } \seealso{ -\link{aemet_munic} for municipality codes. +\link{aemet_munic} for municipality codes and \CRANpkg{mapSpain} package for +working with \code{sf} objects of municipalities (see +\code{mapSpain::esp_get_munic()}). Other aemet_api_data: \code{\link{aemet_daily_clim}()}, diff --git a/man/aemet_last_obs.Rd b/man/aemet_last_obs.Rd index 8904dc8e..214cf012 100644 --- a/man/aemet_last_obs.Rd +++ b/man/aemet_last_obs.Rd @@ -8,7 +8,8 @@ aemet_last_obs( station = "all", verbose = FALSE, return_sf = FALSE, - extract_metadata = FALSE + extract_metadata = FALSE, + progress = TRUE ) } \arguments{ @@ -26,6 +27,9 @@ you need to have the \CRANpkg{sf} package installed.} \item{extract_metadata}{Logical \code{TRUE/FALSE}. On \code{TRUE} the output is a \code{\link[tibble:tibble]{tibble}} with the description of the fields. See also \code{\link[=get_metadata_aemet]{get_metadata_aemet()}}.} + +\item{progress}{Logical, display a \code{\link[cli:cli_progress_bar]{cli::cli_progress_bar()}} object. If +\code{verbose = TRUE} won't be displayed.} } \value{ A \code{\link[tibble:tibble]{tibble}} or a \CRANpkg{sf} object diff --git a/man/aemet_monthly.Rd b/man/aemet_monthly.Rd index b88fb7b8..be9ec814 100644 --- a/man/aemet_monthly.Rd +++ b/man/aemet_monthly.Rd @@ -12,7 +12,8 @@ aemet_monthly_clim( year = as.integer(format(Sys.Date(), "\%Y")), verbose = FALSE, return_sf = FALSE, - extract_metadata = FALSE + extract_metadata = FALSE, + progress = TRUE ) aemet_monthly_period( @@ -21,7 +22,8 @@ aemet_monthly_period( end = start, verbose = FALSE, return_sf = FALSE, - extract_metadata = FALSE + extract_metadata = FALSE, + progress = TRUE ) aemet_monthly_period_all( @@ -29,14 +31,15 @@ aemet_monthly_period_all( end = start, verbose = FALSE, return_sf = FALSE, - extract_metadata = FALSE + extract_metadata = FALSE, + progress = TRUE ) } \arguments{ \item{station}{Character string with station identifier code(s) -(see \code{\link[=aemet_stations]{aemet_stations()}})} +(see \code{\link[=aemet_stations]{aemet_stations()}}).} -\item{year}{Numeric value as date (format: YYYY).} +\item{year}{Numeric value as date (format: \code{YYYY}).} \item{verbose}{Logical \code{TRUE/FALSE}. Provides information about the flow of information between the client and server.} @@ -50,12 +53,15 @@ you need to have the \CRANpkg{sf} package installed.} a \code{\link[tibble:tibble]{tibble}} with the description of the fields. See also \code{\link[=get_metadata_aemet]{get_metadata_aemet()}}.} -\item{start}{Numeric value as start year (format: YYYY).} +\item{progress}{Logical, display a \code{\link[cli:cli_progress_bar]{cli::cli_progress_bar()}} object. If +\code{verbose = TRUE} won't be displayed.} -\item{end}{Numeric value as end year (format: YYYY).} +\item{start}{Numeric value as start year (format: \code{YYYY}).} + +\item{end}{Numeric value as end year (format: \code{YYYY}).} } \value{ -A \code{\link[tibble:tibble]{tibble}} or a \CRANpkg{sf} object +A \code{\link[tibble:tibble]{tibble}} or a \CRANpkg{sf} object. } \description{ Get monthly/annual climatology values for a station or all the stations. diff --git a/man/aemet_normal.Rd b/man/aemet_normal.Rd index 2e601053..282e4af6 100644 --- a/man/aemet_normal.Rd +++ b/man/aemet_normal.Rd @@ -10,13 +10,15 @@ aemet_normal_clim( station = NULL, verbose = FALSE, return_sf = FALSE, - extract_metadata = FALSE + extract_metadata = FALSE, + progress = TRUE ) aemet_normal_clim_all( verbose = FALSE, return_sf = FALSE, - extract_metadata = FALSE + extract_metadata = FALSE, + progress = TRUE ) } \arguments{ @@ -34,17 +36,19 @@ you need to have the \CRANpkg{sf} package installed.} \item{extract_metadata}{Logical \code{TRUE/FALSE}. On \code{TRUE} the output is a \code{\link[tibble:tibble]{tibble}} with the description of the fields. See also \code{\link[=get_metadata_aemet]{get_metadata_aemet()}}.} + +\item{progress}{Logical, display a \code{\link[cli:cli_progress_bar]{cli::cli_progress_bar()}} object. If +\code{verbose = TRUE} won't be displayed.} } \value{ -A \code{\link[tibble:tibble]{tibble}} or a \CRANpkg{sf} object +A \code{\link[tibble:tibble]{tibble}} or a \CRANpkg{sf} object. } \description{ Get normal climatology values for a station (or all the stations with \code{aemet_normal_clim_all()}. Standard climatology from 1981 to 2010. } \note{ -Code modified from project -\url{https://github.com/SevillaR/aemet} +Code modified from project \url{https://github.com/SevillaR/aemet}. } \section{API Key}{ You need to set your API Key globally using \code{\link[=aemet_api_key]{aemet_api_key()}}. diff --git a/man/aemet_stations.Rd b/man/aemet_stations.Rd index bba8bacf..b2173d6b 100644 --- a/man/aemet_stations.Rd +++ b/man/aemet_stations.Rd @@ -16,7 +16,7 @@ Should the function return an \code{\link[sf:sf]{sf}} spatial object? If \code{F you need to have the \CRANpkg{sf} package installed.} } \value{ -A \code{\link[tibble:tibble]{tibble}} or a \CRANpkg{sf} object +A \code{\link[tibble:tibble]{tibble}} or a \CRANpkg{sf} object. } \description{ Get AEMET stations. @@ -26,7 +26,7 @@ The first result of the API call on each session is (temporarily) cached in the assigned \code{\link[=tempdir]{tempdir()}} for avoiding unneeded API calls. } \note{ -Code modified from project \url{https://github.com/SevillaR/aemet} +Code modified from project \url{https://github.com/SevillaR/aemet}. } \section{API Key}{ You need to set your API Key globally using \code{\link[=aemet_api_key]{aemet_api_key()}}. diff --git a/man/climatestripes_station.Rd b/man/climatestripes_station.Rd index ea49a393..c29e0698 100644 --- a/man/climatestripes_station.Rd +++ b/man/climatestripes_station.Rd @@ -15,11 +15,11 @@ climatestripes_station( } \arguments{ \item{station}{Character string with station identifier code(s) -(see \code{\link[=aemet_stations]{aemet_stations()}})} +(see \code{\link[=aemet_stations]{aemet_stations()}}).} -\item{start}{Numeric value as start year (format: YYYY).} +\item{start}{Numeric value as start year (format: \code{YYYY}).} -\item{end}{Numeric value as end year (format: YYYY).} +\item{end}{Numeric value as end year (format: \code{YYYY}).} \item{with_labels}{Character string as yes/no. Indicates whether to use labels for the graph or not.} @@ -31,7 +31,7 @@ information between the client and server.} Arguments passed on to \code{\link[=ggstripes]{ggstripes}} \describe{ \item{\code{n_temp}}{Numeric value as the number of colors of the palette. -(default 11).} +(default \code{11}).} \item{\code{col_pal}}{Character string indicating the name of the \code{\link[=hcl.pals]{hcl.pals()}} color palette to be used for plotting.} }} @@ -40,7 +40,7 @@ information between the client and server.} A \CRANpkg{ggplot2} object } \description{ -Plot climate stripes graph for a station +Plot climate stripes graph for a station. } \section{API Key}{ You need to set your API Key globally using \code{\link[=aemet_api_key]{aemet_api_key()}}. diff --git a/man/climatogram_normal.Rd b/man/climatogram_normal.Rd index d050f0df..b4d3f9e6 100644 --- a/man/climatogram_normal.Rd +++ b/man/climatogram_normal.Rd @@ -14,10 +14,10 @@ climatogram_normal( } \arguments{ \item{station}{Character string with station identifier code(s) -(see \code{\link[=aemet_stations]{aemet_stations()}})} +(see \code{\link[=aemet_stations]{aemet_stations()}}).} -\item{labels}{Character string as month labels for the X axis: "en" -(english), "es" (spanish), "fr" (french), etc.} +\item{labels}{Character string as month labels for the X axis: \code{"en"} +(english), \code{"es"} (spanish), \code{"fr"} (french), etc.} \item{verbose}{Logical \code{TRUE/FALSE}. Provides information about the flow of information between the client and server.} @@ -38,7 +38,7 @@ a station. This climatogram are great for showing a summary of climate conditions for a place over a time period (1981-2010). } \note{ -The code is based on code from the CRAN package \CRANpkg{climatol} +The code is based on code from the CRAN package \CRANpkg{climatol}. } \section{API Key}{ You need to set your API Key globally using \code{\link[=aemet_api_key]{aemet_api_key()}}. diff --git a/man/climatogram_period.Rd b/man/climatogram_period.Rd index 1fecde12..8055d27b 100644 --- a/man/climatogram_period.Rd +++ b/man/climatogram_period.Rd @@ -16,14 +16,14 @@ climatogram_period( } \arguments{ \item{station}{Character string with station identifier code(s) -(see \code{\link[=aemet_stations]{aemet_stations()}})} +(see \code{\link[=aemet_stations]{aemet_stations()}}).} -\item{start}{Numeric value as start year (format: YYYY).} +\item{start}{Numeric value as start year (format: \code{YYYY}).} -\item{end}{Numeric value as end year (format: YYYY).} +\item{end}{Numeric value as end year (format: \code{YYYY}).} -\item{labels}{Character string as month labels for the X axis: "en" -(english), "es" (spanish), "fr" (french), etc.} +\item{labels}{Character string as month labels for the X axis: \code{"en"} +(english), \code{"es"} (spanish), \code{"fr"} (french), etc.} \item{verbose}{Logical \code{TRUE/FALSE}. Provides information about the flow of information between the client and server.} @@ -44,7 +44,7 @@ a station. This climatogram are great for showing a summary of climate conditions for a place over a specific time period. } \note{ -The code is based on code from the CRAN package \CRANpkg{climatol} +The code is based on code from the CRAN package \CRANpkg{climatol}. } \section{API Key}{ You need to set your API Key globally using \code{\link[=aemet_api_key]{aemet_api_key()}}. diff --git a/man/figures/README-climatogram-1.png b/man/figures/README-climatogram-1.png index 1f414090..e2871043 100644 Binary files a/man/figures/README-climatogram-1.png and b/man/figures/README-climatogram-1.png differ diff --git a/man/get_data_aemet.Rd b/man/get_data_aemet.Rd index e8faf299..47a78738 100644 --- a/man/get_data_aemet.Rd +++ b/man/get_data_aemet.Rd @@ -5,7 +5,7 @@ \alias{get_metadata_aemet} \title{Client tool for AEMET API} \source{ -\url{https://opendata.aemet.es/dist/index.html} +\url{https://opendata.aemet.es/dist/index.html}. } \usage{ get_data_aemet(apidest, verbose = FALSE) diff --git a/man/ggclimat_walter_lieth.Rd b/man/ggclimat_walter_lieth.Rd index 96a9acfb..fb413f87 100644 --- a/man/ggclimat_walter_lieth.Rd +++ b/man/ggclimat_walter_lieth.Rd @@ -22,18 +22,18 @@ ggclimat_walter_lieth( \arguments{ \item{dat}{Monthly climatic data for which the diagram will be plotted.} -\item{est}{Name of the climatological station} +\item{est}{Name of the climatological station.} -\item{alt}{Altitude of the climatological station} +\item{alt}{Altitude of the climatological station.} -\item{per}{Period on which the averages have been computed} +\item{per}{Period on which the averages have been computed.} -\item{mlab}{Month labels for the X axis. Use 2-digit language code ("en", -"es", etc.). See \code{\link[readr:locale]{readr::locale()}} for info.} +\item{mlab}{Month labels for the X axis. Use 2-digit language code (\code{"en"}, +\code{"es"}, etc.). See \code{\link[readr:locale]{readr::locale()}} for info.} -\item{pcol}{Color pen for precipitation.} +\item{pcol}{Color for precipitation.} -\item{tcol}{Color pen for temperature.} +\item{tcol}{Color for temperature.} \item{pfcol}{Fill color for probable frosts.} diff --git a/man/ggstripes.Rd b/man/ggstripes.Rd index 5d6adff3..7ce952d8 100644 --- a/man/ggstripes.Rd +++ b/man/ggstripes.Rd @@ -14,16 +14,16 @@ ggstripes( ) } \arguments{ -\item{data}{a data.frame with date(year) and temperature(temp) variables.} +\item{data}{a data.frame with date(\code{year}) and temperature(\code{temp}) variables.} \item{plot_type}{plot type (with labels, background, stripes with line -trend and animation). Accepted values are "background", "stripes", -"trend" or "animation".} +trend and animation). Accepted values are \code{"background"}, \code{"stripes"}, +\code{"trend"} or \code{"animation"}.} \item{plot_title}{character string to be used for the graph title.} \item{n_temp}{Numeric value as the number of colors of the palette. -(default 11).} +(default \code{11}).} \item{col_pal}{Character string indicating the name of the \code{\link[=hcl.pals]{hcl.pals()}} color palette to be used for plotting.} diff --git a/man/ggwindrose.Rd b/man/ggwindrose.Rd index 995f8a62..ddfc2612 100644 --- a/man/ggwindrose.Rd +++ b/man/ggwindrose.Rd @@ -25,10 +25,10 @@ ggwindrose( \item{direction}{Numeric vector of wind directions.} \item{n_directions}{Numeric value as the number of direction bins to plot -(petals on the rose). The number of directions defaults to 8.} +(petals on the rose). The number of directions defaults to \code{8}.} \item{n_speeds}{Numeric value as the number of equally spaced wind speed -bins to plot. This is used if \code{speed_cuts} is \code{NA} (default 5).} +bins to plot. This is used if \code{speed_cuts} is \code{NA} (default \code{5}).} \item{speed_cuts}{Numeric vector containing the cut points for the wind speed intervals, or \code{NA} (default).} @@ -39,7 +39,7 @@ speed intervals, or \code{NA} (default).} \item{legend_title}{Character string to be used for the legend title.} \item{calm_wind}{Numeric value as the upper limit for wind speed that is -considered calm (default 0).} +considered calm (default \code{0}).} \item{n_col}{The number of columns of plots (default 1).} @@ -51,7 +51,7 @@ various windroses.} \item{...}{further arguments (ignored).} } \value{ -A \CRANpkg{ggplot2} object +A \CRANpkg{ggplot2} object\code{.} } \description{ Plot a windrose showing the wind speed and direction using \CRANpkg{ggplot2}. diff --git a/man/windrose_days.Rd b/man/windrose_days.Rd index a1d114ea..c2279028 100644 --- a/man/windrose_days.Rd +++ b/man/windrose_days.Rd @@ -21,15 +21,15 @@ windrose_days( \item{station}{Character string with station identifier code(s) (see \code{\link[=aemet_stations]{aemet_stations()}}) or "all" for all the stations.} -\item{start}{Character string as start date (format: YYYY-MM-DD).} +\item{start}{Character string as start date (format: \code{"YYYY-MM-DD"}).} -\item{end}{Character string as end date (format: YYYY-MM-DD).} +\item{end}{Character string as end date (format: \code{"YYYY-MM-DD"}).} \item{n_directions}{Numeric value as the number of direction bins to plot -(petals on the rose). The number of directions defaults to 8.} +(petals on the rose). The number of directions defaults to \code{8}.} \item{n_speeds}{Numeric value as the number of equally spaced wind speed -bins to plot. This is used if \code{speed_cuts} is \code{NA} (default 5).} +bins to plot. This is used if \code{speed_cuts} is \code{NA} (default \code{5}).} \item{speed_cuts}{Numeric vector containing the cut points for the wind speed intervals, or \code{NA} (default).} @@ -38,7 +38,7 @@ speed intervals, or \code{NA} (default).} \code{\link[=hcl.pals]{hcl.pals()}} color palette to be used for plotting.} \item{calm_wind}{Numeric value as the upper limit for wind speed that is -considered calm (default 0).} +considered calm (default \code{0}).} \item{legend_title}{Character string to be used for the legend title.} @@ -46,7 +46,7 @@ considered calm (default 0).} information between the client and server.} } \value{ -A \CRANpkg{ggplot2} object +A \CRANpkg{ggplot2} object. } \description{ Plot a windrose showing the wind speed and direction for a station over a diff --git a/man/windrose_period.Rd b/man/windrose_period.Rd index 8372281c..f742bdcc 100644 --- a/man/windrose_period.Rd +++ b/man/windrose_period.Rd @@ -21,15 +21,15 @@ windrose_period( \item{station}{Character string with station identifier code(s) (see \code{\link[=aemet_stations]{aemet_stations()}}) or "all" for all the stations.} -\item{start}{Numeric value as start year (format: YYYY).} +\item{start}{Numeric value as start year (format: \code{YYYY}).} -\item{end}{Numeric value as end year (format: YYYY).} +\item{end}{Numeric value as end year (format: \code{YYYY}).} \item{n_directions}{Numeric value as the number of direction bins to plot -(petals on the rose). The number of directions defaults to 8.} +(petals on the rose). The number of directions defaults to \code{8}.} \item{n_speeds}{Numeric value as the number of equally spaced wind speed -bins to plot. This is used if \code{speed_cuts} is \code{NA} (default 5).} +bins to plot. This is used if \code{speed_cuts} is \code{NA} (default \code{5}).} \item{speed_cuts}{Numeric vector containing the cut points for the wind speed intervals, or \code{NA} (default).} @@ -38,7 +38,7 @@ speed intervals, or \code{NA} (default).} \code{\link[=hcl.pals]{hcl.pals()}} color palette to be used for plotting.} \item{calm_wind}{Numeric value as the upper limit for wind speed that is -considered calm (default 0).} +considered calm (default \code{0}).} \item{legend_title}{Character string to be used for the legend title.} diff --git a/tests/testthat.R b/tests/testthat.R new file mode 100644 index 00000000..c597ccf5 --- /dev/null +++ b/tests/testthat.R @@ -0,0 +1,12 @@ +# This file is part of the standard setup for testthat. +# It is recommended that you do not modify it. +# +# Where should you do additional test configuration? +# Learn more about the roles of various files in: +# * https://r-pkgs.org/testing-design.html#sec-tests-files-overview +# * https://testthat.r-lib.org/articles/special-files.html + +library(testthat) +library(climaemet) + +test_check("climaemet") diff --git a/tests/testthat/_snaps/aemet_api_key.md b/tests/testthat/_snaps/aemet_api_key.md new file mode 100644 index 00000000..0cf7245b --- /dev/null +++ b/tests/testthat/_snaps/aemet_api_key.md @@ -0,0 +1,16 @@ +# Load at init the keys + + Code + aemet_daily_clim() + Condition + Error: + ! API key can't be missing. See ??aemet_api_key. + +--- + + Code + aemet_daily_clim(extract_metadata = TRUE) + Condition + Error: + ! API key can't be missing. See ??aemet_api_key. + diff --git a/tests/testthat/_snaps/aemet_api_query.md b/tests/testthat/_snaps/aemet_api_query.md new file mode 100644 index 00000000..931067e3 --- /dev/null +++ b/tests/testthat/_snaps/aemet_api_query.md @@ -0,0 +1,9 @@ +# Manual request + + Code + tt <- get_data_aemet(today) + Message + + Results are MIME type: text/plain + Returning data as string + diff --git a/tests/testthat/_snaps/aemet_daily.md b/tests/testthat/_snaps/aemet_daily.md new file mode 100644 index 00000000..e2ada25d --- /dev/null +++ b/tests/testthat/_snaps/aemet_daily.md @@ -0,0 +1,96 @@ +# Errors and validations + + Code + aemet_daily_clim(NULL) + Condition + Error in `aemet_daily_clim()`: + ! Station can't be missing + +--- + + Code + aemet_daily_clim(start = "aa") + Condition + Error in `charToDate()`: + ! character string is not in a standard unambiguous format + +--- + + Code + aemet_daily_clim(return_sf = "aa") + Condition + Error in `aemet_daily_clim()`: + ! is.logical(return_sf) is not TRUE + +--- + + Code + aemet_daily_clim(verbose = "aa") + Condition + Error in `aemet_daily_clim()`: + ! is.logical(verbose) is not TRUE + +--- + + Code + aemet_daily_period("a", start = NULL) + Condition + Error in `aemet_daily_period()`: + ! Start year can't be missing + +--- + + Code + aemet_daily_period("a", end = NULL) + Condition + Error in `aemet_daily_period()`: + ! End year can't be missing + +--- + + Code + aemet_daily_period("a", start = "aa") + Condition + Error in `aemet_daily_period()`: + ! Start year need to be numeric + +--- + + Code + aemet_daily_period("a", end = "aa") + Condition + Error in `aemet_daily_period()`: + ! End year need to be numeric + +--- + + Code + aemet_daily_period_all(start = NULL) + Condition + Error in `aemet_daily_period_all()`: + ! Start year can't be missing + +--- + + Code + aemet_daily_period_all(end = NULL) + Condition + Error in `aemet_daily_period_all()`: + ! End year can't be missing + +--- + + Code + aemet_daily_period_all(start = "aa") + Condition + Error in `aemet_daily_period_all()`: + ! Start year need to be numeric + +--- + + Code + aemet_daily_period_all(end = "aa") + Condition + Error in `aemet_daily_period_all()`: + ! End year need to be numeric + diff --git a/tests/testthat/_snaps/aemet_extremes.md b/tests/testthat/_snaps/aemet_extremes.md new file mode 100644 index 00000000..e3a763a6 --- /dev/null +++ b/tests/testthat/_snaps/aemet_extremes.md @@ -0,0 +1,32 @@ +# Errors and validations + + Code + aemet_extremes_clim(NULL) + Condition + Error in `aemet_extremes_clim()`: + ! Station can't be missing + +--- + + Code + aemet_extremes_clim("NULL", parameter = NULL) + Condition + Error in `aemet_extremes_clim()`: + ! Parameter can't be missing + +--- + + Code + aemet_extremes_clim("NULL", parameter = TRUE) + Condition + Error in `aemet_extremes_clim()`: + ! Parameter need to be character string + +--- + + Code + aemet_extremes_clim("NULL", parameter = "ABC") + Condition + Error in `aemet_extremes_clim()`: + ! Parameter should be one of 'T', 'P', 'V' + diff --git a/tests/testthat/_snaps/aemet_forecast_daily.md b/tests/testthat/_snaps/aemet_forecast_daily.md new file mode 100644 index 00000000..e08d2b4d --- /dev/null +++ b/tests/testthat/_snaps/aemet_forecast_daily.md @@ -0,0 +1,36 @@ +# Online + + Code + emp <- aemet_forecast_daily("naha") + Condition + Warning in `aemet_api_call()`: + HTTP 404: Error al obtener los datos + Message + + AEMET API call for 'naha' returned an error + Return NULL for this query + Condition + Warning: + Unknown or uninitialised column: `id`. + +--- + + Code + dput(emp) + Output + structure(list(id = character(0)), row.names = integer(0), class = c("tbl_df", + "tbl", "data.frame")) + +--- + + Code + vv <- aemet_forecast_vars_available(alll) + +--- + + Code + aemet_forecast_tidy(alll, "hagaga") + Condition + Error in `aemet_forecast_tidy()`: + ! Var 'hagaga' not available in the current dataset. + diff --git a/tests/testthat/_snaps/aemet_forecast_hourly.md b/tests/testthat/_snaps/aemet_forecast_hourly.md new file mode 100644 index 00000000..f666f3bf --- /dev/null +++ b/tests/testthat/_snaps/aemet_forecast_hourly.md @@ -0,0 +1,36 @@ +# Online + + Code + emp <- aemet_forecast_hourly("naha") + Condition + Warning in `aemet_api_call()`: + HTTP 404: Error al obtener los datos + Message + + AEMET API call for 'naha' returned an error + Return NULL for this query + Condition + Warning: + Unknown or uninitialised column: `id`. + +--- + + Code + dput(emp) + Output + structure(list(id = character(0)), row.names = integer(0), class = c("tbl_df", + "tbl", "data.frame")) + +--- + + Code + vv <- aemet_forecast_vars_available(alll) + +--- + + Code + aemet_forecast_tidy(alll, "hagaga") + Condition + Error in `aemet_forecast_tidy()`: + ! Var 'hagaga' not available in the current dataset. + diff --git a/tests/testthat/_snaps/aemet_last_obs.md b/tests/testthat/_snaps/aemet_last_obs.md new file mode 100644 index 00000000..7a96e9e9 --- /dev/null +++ b/tests/testthat/_snaps/aemet_last_obs.md @@ -0,0 +1,24 @@ +# Errors and validations + + Code + aemet_last_obs(NULL) + Condition + Error in `aemet_last_obs()`: + ! Station can't be missing + +--- + + Code + aemet_last_obs(return_sf = "A") + Condition + Error in `aemet_last_obs()`: + ! is.logical(return_sf) is not TRUE + +--- + + Code + aemet_last_obs(verbose = "A") + Condition + Error in `aemet_last_obs()`: + ! is.logical(verbose) is not TRUE + diff --git a/tests/testthat/_snaps/aemet_monthly.md b/tests/testthat/_snaps/aemet_monthly.md new file mode 100644 index 00000000..5b021e66 --- /dev/null +++ b/tests/testthat/_snaps/aemet_monthly.md @@ -0,0 +1,120 @@ +# Errors and validations + + Code + aemet_monthly_clim(NULL) + Condition + Error in `aemet_monthly_clim()`: + ! Station can't be missing + +--- + + Code + aemet_monthly_clim("a", year = "aa") + Condition + Error in `aemet_monthly_clim()`: + ! Year need to be numeric + +--- + + Code + aemet_monthly_clim("a", return_sf = "aa") + Condition + Error in `aemet_monthly_clim()`: + ! is.logical(return_sf) is not TRUE + +--- + + Code + aemet_monthly_clim("a", verbose = "aa") + Condition + Error in `aemet_monthly_clim()`: + ! is.logical(verbose) is not TRUE + +--- + + Code + aemet_monthly_period("a", start = NULL) + Condition + Error in `aemet_monthly_period()`: + ! Start year need to be numeric + +--- + + Code + aemet_monthly_period("a", end = NULL) + Condition + Error in `aemet_monthly_period()`: + ! End year need to be numeric + +--- + + Code + aemet_monthly_period(NULL, start = "aa") + Condition + Error in `aemet_monthly_period()`: + ! Station can't be missing + +--- + + Code + aemet_monthly_period_all(start = NULL) + Condition + Error in `aemet_monthly_period_all()`: + ! Start year can't be missing + +--- + + Code + aemet_monthly_period_all(end = NULL) + Condition + Error in `aemet_monthly_period_all()`: + ! End year can't be missing + +--- + + Code + aemet_monthly_period_all(start = "NULL") + Condition + Error in `aemet_monthly_period_all()`: + ! Start year need to be numeric + +--- + + Code + aemet_monthly_period_all(end = "NULL") + Condition + Error in `aemet_monthly_period_all()`: + ! End year need to be numeric + +# aemet_monthly_period + + Code + unique(alll$fecha) + Output + [1] "2010-01" "2010-02" "2010-03" "2010-04" "2010-05" "2010-06" "2010-07" + [8] "2010-08" "2010-09" "2010-10" "2010-11" "2010-12" "2010-13" "2011-01" + [15] "2011-02" "2011-03" "2011-04" "2011-05" "2011-06" "2011-07" "2011-08" + [22] "2011-09" "2011-10" "2011-11" "2011-12" "2011-13" "2012-01" "2012-02" + [29] "2012-03" "2012-04" "2012-05" "2012-06" "2012-07" "2012-08" "2012-09" + [36] "2012-10" "2012-11" "2012-12" "2012-13" "2013-01" "2013-02" "2013-03" + [43] "2013-04" "2013-05" "2013-06" "2013-07" "2013-08" "2013-09" "2013-10" + [50] "2013-11" "2013-12" "2013-13" "2014-01" "2014-02" "2014-03" "2014-04" + [57] "2014-05" "2014-06" "2014-07" "2014-08" "2014-09" "2014-10" "2014-11" + [64] "2014-12" "2014-13" "2015-01" "2015-02" "2015-03" "2015-04" "2015-05" + [71] "2015-06" "2015-07" "2015-08" "2015-09" "2015-10" "2015-11" "2015-12" + [78] "2015-13" "2016-01" "2016-02" "2016-03" "2016-04" "2016-05" "2016-06" + [85] "2016-07" "2016-08" "2016-09" "2016-10" "2016-11" "2016-12" "2016-13" + [92] "2017-01" "2017-02" "2017-03" "2017-04" "2017-05" "2017-06" "2017-07" + [99] "2017-08" "2017-09" "2017-10" "2017-11" "2017-12" "2017-13" "2018-01" + [106] "2018-02" "2018-03" "2018-04" "2018-05" "2018-06" "2018-07" "2018-08" + [113] "2018-09" "2018-10" "2018-11" "2018-12" "2018-13" "2019-01" "2019-02" + [120] "2019-03" "2019-04" "2019-05" "2019-06" "2019-07" "2019-08" "2019-09" + [127] "2019-10" "2019-11" "2019-12" "2019-13" "2020-01" "2020-02" "2020-03" + [134] "2020-04" "2020-05" "2020-06" "2020-07" "2020-08" "2020-09" "2020-10" + [141] "2020-11" "2020-12" "2020-13" "2021-01" "2021-02" "2021-03" "2021-04" + [148] "2021-05" "2021-06" "2021-07" "2021-08" "2021-09" "2021-10" "2021-11" + [155] "2021-12" "2021-13" "2022-01" "2022-02" "2022-03" "2022-04" "2022-05" + [162] "2022-06" "2022-07" "2022-08" "2022-09" "2022-10" "2022-11" "2022-12" + [169] "2022-13" "2023-01" "2023-02" "2023-03" "2023-04" "2023-05" "2023-06" + [176] "2023-07" "2023-08" "2023-09" "2023-10" "2023-11" "2023-12" "2023-13" + diff --git a/tests/testthat/_snaps/aemet_normal.md b/tests/testthat/_snaps/aemet_normal.md new file mode 100644 index 00000000..84268bb5 --- /dev/null +++ b/tests/testthat/_snaps/aemet_normal.md @@ -0,0 +1,24 @@ +# Errors and validations + + Code + aemet_normal_clim(NULL) + Condition + Error in `aemet_normal_clim()`: + ! Station can't be missing + +--- + + Code + aemet_normal_clim(return_sf = "A") + Condition + Error in `aemet_normal_clim()`: + ! Station can't be missing + +--- + + Code + aemet_normal_clim(verbose = "A") + Condition + Error in `aemet_normal_clim()`: + ! Station can't be missing + diff --git a/tests/testthat/_snaps/aemet_stations.md b/tests/testthat/_snaps/aemet_stations.md new file mode 100644 index 00000000..8cbc66ed --- /dev/null +++ b/tests/testthat/_snaps/aemet_stations.md @@ -0,0 +1,16 @@ +# Errors and validations + + Code + aemet_stations(return_sf = "A") + Condition + Error in `aemet_stations()`: + ! is.logical(return_sf) is not TRUE + +--- + + Code + aemet_stations(verbose = "A") + Condition + Error in `aemet_stations()`: + ! is.logical(verbose) is not TRUE + diff --git a/tests/testthat/_snaps/helpers.md b/tests/testthat/_snaps/helpers.md new file mode 100644 index 00000000..b291cdb1 --- /dev/null +++ b/tests/testthat/_snaps/helpers.md @@ -0,0 +1,50 @@ +# dms2decdegrees works + + Code + dms2decdegrees("055245W") + Output + [1] -5.879167 + +--- + + Code + dms2decdegrees("522312N") + Output + [1] 52.38667 + +# dms2decdegrees_2 works + + Code + dms2decdegrees_2("-5º 52' 45\"") + Output + [1] -5.879167 + +--- + + Code + dms2decdegrees_2("52º 23'12\"") + Output + [1] 52.38667 + +--- + + Code + dms2decdegrees_2("52º 2312\"") + Condition + Error in `dms2decdegrees_2()`: + ! Something went wrong + +# first and last works + + Code + first_day_of_year(2000) + Output + [1] "2000-01-01" + +--- + + Code + last_day_of_year(2020) + Output + [1] "2020-12-31" + diff --git a/tests/testthat/_snaps/utils.md b/tests/testthat/_snaps/utils.md new file mode 100644 index 00000000..7ce67132 --- /dev/null +++ b/tests/testthat/_snaps/utils.md @@ -0,0 +1,22 @@ +# Check sf + + Code + bad <- aemet_hlp_sf(ex, "lat", "lon", verbose = FALSE) + Message + lat/lon columns not found. Returning a tibble + +--- + + Code + a <- aemet_hlp_sf(ex, "cpro", "codauto", verbose = TRUE) + Message + Converting to spatial object + spatial conversion succesful + +--- + + Code + bad2 <- aemet_hlp_sf(ex, "cpro", "codauto", verbose = FALSE) + Message + Found NA coordinates. Returning a tibble + diff --git a/tests/testthat/test-aemet_api_key.R b/tests/testthat/test-aemet_api_key.R new file mode 100644 index 00000000..f1ada55c --- /dev/null +++ b/tests/testthat/test-aemet_api_key.R @@ -0,0 +1,68 @@ +test_that("Detection", { + skip_on_cran() + skip_if_offline() + skip_if_not(aemet_detect_api_key(), message = "No API KEY") + + # Internal + int <- aemet_hlp_get_allkeys() + exp <- aemet_show_api_key() + expect_identical(int, exp) +}) + + +test_that("Load at init the keys", { + skip_on_cran() + skip_if_offline() + skip_if_not(aemet_detect_api_key(), message = "No API KEY") + + # recover keys and install + the_keys <- aemet_show_api_key() + aemet_api_key(the_keys, install = TRUE, overwrite = TRUE) + + # For safety, create a backup copy + keydir <- rappdirs::user_cache_dir("climaemet", "R") + path_orig <- file.path(keydir, "aemet_api_key") + path_bk <- file.path(tempdir(), "aemet_api_key") + + unlink(path_bk) + file.copy(path_orig, path_bk, overwrite = TRUE) + + # Now start to mess up with the keys + + # Uninstall from the env + allk <- names(Sys.getenv()) + envk <- allk[grepl("AEMET_API_KEY", allk)] + + for (k in envk) { + Sys.unsetenv(k) + } + + # Delete cache dir + unlink(keydir, force = TRUE, recursive = TRUE) + expect_false(aemet_detect_api_key()) + + expect_snapshot(aemet_daily_clim(), error = TRUE) + expect_snapshot(aemet_daily_clim(extract_metadata = TRUE), error = TRUE) + + + expect_identical(aemet_show_api_key(), character(0)) + + # Install and overwrite + expect_message(aemet_api_key(the_keys)) + aemet_api_key(the_keys, overwrite = TRUE, install = TRUE) + expect_error(aemet_api_key(the_keys, install = TRUE)) + expect_silent(aemet_api_key(the_keys, install = TRUE, overwrite = TRUE)) + + # Trigger detection + expect_true(aemet_detect_api_key()) + + # Clean the envars and trigger detection again from cache + for (k in envk) { + Sys.unsetenv(k) + } + + expect_true(aemet_detect_api_key()) + # And restore everything + file.copy(path_bk, path_orig, overwrite = TRUE) + expect_identical(aemet_show_api_key(), the_keys) +}) diff --git a/tests/testthat/test-aemet_api_query.R b/tests/testthat/test-aemet_api_query.R new file mode 100644 index 00000000..026e5e80 --- /dev/null +++ b/tests/testthat/test-aemet_api_query.R @@ -0,0 +1,13 @@ +test_that("Manual request", { + skip_on_cran() + skip_if_offline() + skip_if_not(aemet_detect_api_key(), message = "No API KEY") + + + today <- "/api/prediccion/nacional/hoy" + expect_snapshot(tt <- get_data_aemet(today)) + expect_true(is.character(tt)) + + tt2 <- get_metadata_aemet(today) + expect_s3_class(tt2, "tbl_df") +}) diff --git a/tests/testthat/test-aemet_daily.R b/tests/testthat/test-aemet_daily.R new file mode 100644 index 00000000..7cc3b79a --- /dev/null +++ b/tests/testthat/test-aemet_daily.R @@ -0,0 +1,108 @@ +test_that("Errors and validations", { + # Validations aemet_daily clim + expect_snapshot(aemet_daily_clim(NULL), error = TRUE) + expect_snapshot(aemet_daily_clim(start = "aa"), error = TRUE) + expect_snapshot(aemet_daily_clim(return_sf = "aa"), error = TRUE) + expect_snapshot(aemet_daily_clim(verbose = "aa"), error = TRUE) + + # Validations aemet_daily_period + expect_snapshot(aemet_daily_period("a", start = NULL), error = TRUE) + expect_snapshot(aemet_daily_period("a", end = NULL), error = TRUE) + expect_snapshot(aemet_daily_period("a", start = "aa"), error = TRUE) + expect_snapshot(aemet_daily_period("a", end = "aa"), error = TRUE) + + # Validations aemet_daily_period_all + expect_snapshot(aemet_daily_period_all(start = NULL), error = TRUE) + expect_snapshot(aemet_daily_period_all(end = NULL), error = TRUE) + expect_snapshot(aemet_daily_period_all(start = "aa"), error = TRUE) + expect_snapshot(aemet_daily_period_all(end = "aa"), error = TRUE) +}) + +test_that("aemet_daily for all", { + skip_on_cran() + skip_if_offline() + skip_if_not(aemet_detect_api_key(), message = "No API KEY") + + meta <- aemet_daily_clim(extract_metadata = TRUE) + # Same as + meta2 <- aemet_daily_clim("NOEXIST", extract_metadata = TRUE) + expect_identical(meta, meta2) + + # Default + expect_message(alll <- aemet_daily_clim(verbose = TRUE)) + expect_s3_class(alll, "tbl_df") + Sys.sleep(0.5) + alll2 <- aemet_daily_clim() + + expect_identical(alll, alll2) + expect_gt(length(unique(alll$indicativo)), 100) + + + # Past today + Sys.sleep(0.5) + morethantoday <- aemet_daily_clim(end = Sys.Date() + 1, verbose = TRUE) + expect_identical(alll2, morethantoday) + + + # Single day + Sys.sleep(0.5) + alll3 <- aemet_daily_clim(start = Sys.Date() - 20, end = Sys.Date() - 20) + + + expect_s3_class(alll3, "tbl_df") + + # More days + Sys.sleep(0.5) + alll_more <- aemet_daily_clim(start = "2023-01-01", end = "2023-02-15") + + # sf + Sys.sleep(0.5) + alll_sf <- aemet_daily_clim(return_sf = TRUE) + + expect_s3_class(alll_sf, "sf") + expect_true(unique(sf::st_geometry_type(alll_sf)) == "POINT") +}) + +test_that("aemet_daily iterations", { + skip_on_cran() + skip_if_offline() + skip_if_not(aemet_detect_api_key(), message = "No API KEY") + + st_demo <- aemet_stations()$indicativo[1:3] + # Default + alll <- aemet_daily_clim(st_demo) + expect_s3_class(alll, "tbl_df") + expect_identical(unique(alll$indicativo), st_demo) + + # More days + Sys.sleep(0.5) + alll_more <- aemet_daily_clim(st_demo, + start = "2023-01-01", + end = "2023-06-30" + ) + expect_s3_class(alll_more, "tbl_df") + expect_identical(unique(alll_more$indicativo), st_demo) + + + # sf + Sys.sleep(0.5) + alll_sf <- aemet_daily_clim(st_demo, return_sf = TRUE) + + expect_identical(unique(alll_sf$indicativo), st_demo) + expect_s3_class(alll_sf, "sf") + expect_true(unique(sf::st_geometry_type(alll_sf)) == "POINT") +}) + +test_that("aemet_daily_period", { + skip_on_cran() + skip_if_offline() + skip_if_not(aemet_detect_api_key(), message = "No API KEY") + + st_demo <- aemet_stations()$indicativo[1] + # Default + alll <- aemet_daily_period(st_demo, start = 2023, end = 2023) + expect_s3_class(alll, "tbl_df") + expect_identical(unique(alll$indicativo), st_demo) + + expect_gt(length(unique(alll$fecha)), 200) +}) diff --git a/tests/testthat/test-aemet_extremes.R b/tests/testthat/test-aemet_extremes.R new file mode 100644 index 00000000..c7600509 --- /dev/null +++ b/tests/testthat/test-aemet_extremes.R @@ -0,0 +1,54 @@ +test_that("Errors and validations", { + # Validations + expect_snapshot(aemet_extremes_clim(NULL), error = TRUE) + expect_snapshot(aemet_extremes_clim("NULL", parameter = NULL), error = TRUE) + expect_snapshot(aemet_extremes_clim("NULL", parameter = TRUE), error = TRUE) + expect_snapshot(aemet_extremes_clim("NULL", parameter = "ABC"), error = TRUE) +}) + + +test_that("Online", { + skip_on_cran() + skip_if_offline() + skip_if_not(aemet_detect_api_key(), message = "No API KEY") + + st <- c("9434", "3195") + meta <- aemet_extremes_clim("all", extract_metadata = TRUE) + # Same as + meta2 <- aemet_extremes_clim("NOEXIST", extract_metadata = TRUE) + expect_identical(meta, meta2) + + # Default + expect_message(alll <- aemet_extremes_clim(st, verbose = TRUE)) + expect_s3_class(alll, "tbl_df") + + expect_identical(unique(alll$indicativo), st) + + + # Other params + alll_p <- aemet_extremes_clim(st, parameter = "P") + alll_v <- aemet_extremes_clim(st, parameter = "V") + + expect_false(identical(alll_p, alll)) + expect_false(identical(alll_p, alll_v)) + expect_false(identical(alll_v, alll)) + + # sf + Sys.sleep(0.5) + alll_sf <- aemet_extremes_clim(st, return_sf = TRUE) + + expect_s3_class(alll_sf, "sf") + expect_true(unique(sf::st_geometry_type(alll_sf)) == "POINT") +}) + +test_that("Parsing errors", { + skip_on_cran() + skip_if_offline() + skip_if_not(aemet_detect_api_key(), message = "No API KEY") + + expect_message(v <- aemet_extremes_clim("B013X", parameter = "V")) + expect_true(is.list(v)) + + expect_message(p <- aemet_extremes_clim("B013X", parameter = "P")) + expect_true(is.list(p)) +}) diff --git a/tests/testthat/test-aemet_forecast_daily.R b/tests/testthat/test-aemet_forecast_daily.R new file mode 100644 index 00000000..4f46cb36 --- /dev/null +++ b/tests/testthat/test-aemet_forecast_daily.R @@ -0,0 +1,44 @@ +test_that("Online", { + skip_on_cran() + skip_if_offline() + skip_if_not(aemet_detect_api_key(), message = "No API KEY") + + meta <- aemet_forecast_daily("a", extract_metadata = TRUE) + # Same as + meta2 <- aemet_forecast_daily("NOEXIST", + extract_metadata = TRUE, + verbose = TRUE + ) + expect_identical(meta, meta2) + + + st <- aemet_munic$municipio[1:3] + + # Default + expect_message(alll <- aemet_forecast_daily(st, verbose = TRUE)) + expect_s3_class(alll, "tbl_df") + expect_identical(unique(alll$municipio), st) + + # Same as + stn <- as.numeric(st) + + allln <- aemet_forecast_daily(stn) + expect_identical(alll, allln) + # NUll + expect_snapshot(emp <- aemet_forecast_daily("naha")) + + expect_s3_class(emp, "tbl_df") + expect_equal(nrow(emp), 0) + expect_snapshot(dput(emp)) + + # Extract some vars + expect_snapshot(vv <- aemet_forecast_vars_available(alll)) + + expect_snapshot(aemet_forecast_tidy(alll, "hagaga"), error = TRUE) + + # Extract everythig + for (v in vv) { + tt <- aemet_forecast_tidy(alll, v) + expect_s3_class(tt, "tbl_df") + } +}) diff --git a/tests/testthat/test-aemet_forecast_hourly.R b/tests/testthat/test-aemet_forecast_hourly.R new file mode 100644 index 00000000..90a399e5 --- /dev/null +++ b/tests/testthat/test-aemet_forecast_hourly.R @@ -0,0 +1,44 @@ +test_that("Online", { + skip_on_cran() + skip_if_offline() + skip_if_not(aemet_detect_api_key(), message = "No API KEY") + + meta <- aemet_forecast_hourly("a", extract_metadata = TRUE) + # Same as + meta2 <- aemet_forecast_hourly("NOEXIST", + extract_metadata = TRUE, + verbose = TRUE + ) + expect_identical(meta, meta2) + + + st <- aemet_munic$municipio[1:3] + + # Default + expect_message(alll <- aemet_forecast_hourly(st, verbose = TRUE)) + expect_s3_class(alll, "tbl_df") + expect_identical(unique(alll$municipio), st) + + # Same as + stn <- as.numeric(st) + + allln <- aemet_forecast_hourly(stn) + expect_identical(alll, allln) + # NUll + expect_snapshot(emp <- aemet_forecast_hourly("naha")) + + expect_s3_class(emp, "tbl_df") + expect_equal(nrow(emp), 0) + expect_snapshot(dput(emp)) + + # Extract some vars + expect_snapshot(vv <- aemet_forecast_vars_available(alll)) + + expect_snapshot(aemet_forecast_tidy(alll, "hagaga"), error = TRUE) + + # Extract everythig + for (v in vv) { + tt <- aemet_forecast_tidy(alll, v) + expect_s3_class(tt, "tbl_df") + } +}) diff --git a/tests/testthat/test-aemet_last_obs.R b/tests/testthat/test-aemet_last_obs.R new file mode 100644 index 00000000..2ed1dddf --- /dev/null +++ b/tests/testthat/test-aemet_last_obs.R @@ -0,0 +1,38 @@ +test_that("Errors and validations", { + # Validations + expect_snapshot(aemet_last_obs(NULL), error = TRUE) + expect_snapshot(aemet_last_obs(return_sf = "A"), error = TRUE) + expect_snapshot(aemet_last_obs(verbose = "A"), error = TRUE) +}) + +test_that("Online", { + skip_on_cran() + skip_if_offline() + skip_if_not(aemet_detect_api_key(), message = "No API KEY") + + st <- c("9434", "3195") + meta <- aemet_last_obs(extract_metadata = TRUE) + # Same as + meta2 <- aemet_last_obs("NOEXIST", extract_metadata = TRUE) + expect_identical(meta, meta2) + + # Default + expect_message(alll <- aemet_last_obs(verbose = TRUE)) + expect_s3_class(alll, "tbl_df") + + # If any is all ignore + alll2 <- aemet_last_obs(c("all", "IDONOT")) + expect_identical(alll, alll2) + + # Several + sev <- aemet_last_obs(st) + expect_identical(unique(sev$idema), st) + + + # sf + Sys.sleep(0.5) + alll_sf <- aemet_last_obs(st, return_sf = TRUE) + + expect_s3_class(alll_sf, "sf") + expect_true(unique(sf::st_geometry_type(alll_sf)) == "POINT") +}) diff --git a/tests/testthat/test-aemet_monthly.R b/tests/testthat/test-aemet_monthly.R new file mode 100644 index 00000000..c83330c7 --- /dev/null +++ b/tests/testthat/test-aemet_monthly.R @@ -0,0 +1,97 @@ +test_that("Errors and validations", { + # Validations aemet_monthly_clim + expect_snapshot(aemet_monthly_clim(NULL), error = TRUE) + expect_snapshot(aemet_monthly_clim("a", year = "aa"), error = TRUE) + expect_snapshot(aemet_monthly_clim("a", return_sf = "aa"), error = TRUE) + expect_snapshot(aemet_monthly_clim("a", verbose = "aa"), error = TRUE) + + # Validations aemet_monthly_period + expect_snapshot(aemet_monthly_period("a", start = NULL), error = TRUE) + expect_snapshot(aemet_monthly_period("a", end = NULL), error = TRUE) + expect_snapshot(aemet_monthly_period(NULL, start = "aa"), error = TRUE) + + # Validations aemet_monthly_period_all + expect_snapshot(aemet_monthly_period_all(start = NULL), error = TRUE) + expect_snapshot(aemet_monthly_period_all(end = NULL), error = TRUE) + expect_snapshot(aemet_monthly_period_all(start = "NULL"), error = TRUE) + expect_snapshot(aemet_monthly_period_all(end = "NULL"), error = TRUE) +}) + +test_that("aemet_monthly", { + skip_on_cran() + skip_if_offline() + skip_if_not(aemet_detect_api_key(), message = "No API KEY") + + meta <- aemet_monthly_clim("a", extract_metadata = TRUE) + # Same as + meta2 <- aemet_monthly_clim("NOEXIST", + extract_metadata = TRUE, + verbose = TRUE + ) + expect_identical(meta, meta2) + + # Same as + meta3 <- aemet_monthly_period("NOEXIST", extract_metadata = TRUE) + expect_identical(meta, meta3) + + # Same as + meta4 <- aemet_monthly_period_all(extract_metadata = TRUE) + expect_identical(meta, meta4) + + + st <- c("9434", "3195") + + # Default + expect_message(alll <- aemet_monthly_clim(st, verbose = TRUE)) + expect_s3_class(alll, "tbl_df") + + expect_identical(unique(alll$indicativo), st) + + # maxfechas + alll2 <- aemet_monthly_clim(st, year = 2029) + + + expect_identical(alll, alll2) + + # sf + Sys.sleep(0.5) + alll_sf <- aemet_monthly_clim(st, return_sf = TRUE) + + expect_s3_class(alll_sf, "sf") + expect_true(unique(sf::st_geometry_type(alll_sf)) == "POINT") +}) + + +test_that("aemet_monthly_period", { + skip_on_cran() + skip_if_offline() + skip_if_not(aemet_detect_api_key(), message = "No API KEY") + + + st <- c("9434", "3195") + + # Default + expect_message(alll <- aemet_monthly_period(st, verbose = TRUE)) + expect_s3_class(alll, "tbl_df") + + expect_identical(unique(alll$indicativo), st) + + # maxfechas + alll2 <- aemet_monthly_period(st, end = 4000) + expect_identical(alll, alll2) + + # Others + alll <- aemet_monthly_period(st, start = 2010, end = 2023) + expect_snapshot(unique(alll$fecha)) + + + # sf + Sys.sleep(0.5) + alll_sf <- aemet_monthly_period(st, + start = 2020, end = 2023, + return_sf = TRUE + ) + + expect_s3_class(alll_sf, "sf") + expect_true(unique(sf::st_geometry_type(alll_sf)) == "POINT") +}) diff --git a/tests/testthat/test-aemet_normal.R b/tests/testthat/test-aemet_normal.R new file mode 100644 index 00000000..abb51bc0 --- /dev/null +++ b/tests/testthat/test-aemet_normal.R @@ -0,0 +1,36 @@ +test_that("Errors and validations", { + # Validations + expect_snapshot(aemet_normal_clim(NULL), error = TRUE) + expect_snapshot(aemet_normal_clim(return_sf = "A"), error = TRUE) + expect_snapshot(aemet_normal_clim(verbose = "A"), error = TRUE) +}) + +test_that("Online", { + skip_on_cran() + skip_if_offline() + skip_if_not(aemet_detect_api_key(), message = "No API KEY") + + st <- c("9434", "3195") + meta <- aemet_normal_clim("a", extract_metadata = TRUE) + # Same as + meta2 <- aemet_normal_clim("NOEXIST", extract_metadata = TRUE) + expect_identical(meta, meta2) + + # And + meta3 <- aemet_normal_clim_all(extract_metadata = TRUE) + expect_identical(meta3, meta2) + + # Default + expect_message(alll <- aemet_normal_clim(st, verbose = TRUE)) + expect_s3_class(alll, "tbl_df") + + expect_identical(unique(alll$indicativo), st) + + + # sf + Sys.sleep(0.5) + alll_sf <- aemet_normal_clim(st, return_sf = TRUE) + + expect_s3_class(alll_sf, "sf") + expect_true(unique(sf::st_geometry_type(alll_sf)) == "POINT") +}) diff --git a/tests/testthat/test-aemet_stations.R b/tests/testthat/test-aemet_stations.R new file mode 100644 index 00000000..e5a0b749 --- /dev/null +++ b/tests/testthat/test-aemet_stations.R @@ -0,0 +1,38 @@ +test_that("Errors and validations", { + # Validations + expect_snapshot(aemet_stations(return_sf = "A"), error = TRUE) + expect_snapshot(aemet_stations(verbose = "A"), error = TRUE) +}) + + +test_that("Online", { + skip_on_cran() + skip_if_offline() + skip_if_not(aemet_detect_api_key(), message = "No API KEY") + + # First clean cache + cached_df <- file.path(tempdir(), "aemet_stations.rds") + cached_date <- file.path(tempdir(), "aemet_stations_date.rds") + unlink(cached_df) + unlink(cached_date) + + # First download + expect_message(aemet_stations(verbose = TRUE), + regexp = "Using API KEY X" + ) + + # Now is cached + expect_message(aemet_stations(verbose = TRUE), + regexp = "Loading stations from temporal cached file" + ) + + st1 <- aemet_stations() + expect_s3_class(st1, "tbl_df") + + # sf + Sys.sleep(0.5) + alll_sf <- aemet_stations(return_sf = TRUE) + + expect_s3_class(alll_sf, "sf") + expect_true(unique(sf::st_geometry_type(alll_sf)) == "POINT") +}) diff --git a/tests/testthat/test-helpers.R b/tests/testthat/test-helpers.R new file mode 100644 index 00000000..4b9c8c08 --- /dev/null +++ b/tests/testthat/test-helpers.R @@ -0,0 +1,19 @@ +test_that("dms2decdegrees works", { + expect_snapshot(dms2decdegrees("055245W")) + + expect_snapshot(dms2decdegrees("522312N")) +}) + + +test_that("dms2decdegrees_2 works", { + expect_snapshot(dms2decdegrees_2("-5º 52' 45\"")) + + expect_snapshot(dms2decdegrees_2("52º 23'12\"")) + + expect_snapshot(dms2decdegrees_2("52º 2312\""), error = TRUE) +}) + +test_that("first and last works", { + expect_snapshot(first_day_of_year(2000)) + expect_snapshot(last_day_of_year(2020)) +}) diff --git a/tests/testthat/test-utils.R b/tests/testthat/test-utils.R new file mode 100644 index 00000000..cd2c43bb --- /dev/null +++ b/tests/testthat/test-utils.R @@ -0,0 +1,20 @@ +test_that("Check sf", { + skip_if_not_installed("sf") + + # Example tb + ex <- climaemet::aemet_munic[1:10, ] + + expect_snapshot(bad <- aemet_hlp_sf(ex, "lat", "lon", verbose = FALSE)) + expect_s3_class(bad, "tbl_df") + + expect_silent(asf <- aemet_hlp_sf(ex, "cpro", "codauto")) + + expect_s3_class(asf, "sf") + expect_snapshot(a <- aemet_hlp_sf(ex, "cpro", "codauto", verbose = TRUE)) + + # MOdify and add NAs + ex$cpro[1] <- NA + + expect_snapshot(bad2 <- aemet_hlp_sf(ex, "cpro", "codauto", verbose = FALSE)) + expect_s3_class(bad2, "tbl_df") +}) diff --git a/vignettes/climaemet.Rmd b/vignettes/climaemet.Rmd index 428694e3..62c356ba 100644 --- a/vignettes/climaemet.Rmd +++ b/vignettes/climaemet.Rmd @@ -87,24 +87,24 @@ See how a `tibble` is displayed: # See a tibble in action aemet_last_obs("9434") -#> # A tibble: 12 × 25 -#> idema lon fint prec alt vmax vv dv lat dmax -#> -#> 1 9434 -1.00 2024-06-19 22:00:00 0 249 14.1 8.8 307 41.7 318 -#> 2 9434 -1.00 2024-06-19 23:00:00 0 249 14.5 7.3 300 41.7 293 -#> 3 9434 -1.00 2024-06-20 00:00:00 0 249 9.4 3.9 316 41.7 293 -#> 4 9434 -1.00 2024-06-20 01:00:00 0 249 8.4 5.9 310 41.7 295 -#> 5 9434 -1.00 2024-06-20 02:00:00 0 249 8.4 6.1 309 41.7 323 -#> 6 9434 -1.00 2024-06-20 03:00:00 0 249 10 7.7 298 41.7 298 -#> 7 9434 -1.00 2024-06-20 04:00:00 0 249 10.4 7.2 304 41.7 325 -#> 8 9434 -1.00 2024-06-20 05:00:00 0 249 9.7 6.5 301 41.7 313 -#> 9 9434 -1.00 2024-06-20 06:00:00 4 249 9.2 4.5 304 41.7 305 -#> 10 9434 -1.00 2024-06-20 07:00:00 0 249 9.8 6.9 291 41.7 280 -#> 11 9434 -1.00 2024-06-20 08:00:00 0 249 11 5.1 313 41.7 308 -#> 12 9434 -1.00 2024-06-20 09:00:00 0 249 7.9 4.9 320 41.7 308 -#> # ℹ 15 more variables: ubi , pres , hr , stdvv , ts , -#> # pres_nmar , tamin , ta , tamax , tpr , -#> # stddv , inso , tss5cm , pacutp , tss20cm +#> # A tibble: 13 × 25 +#> idema lon fint prec alt vmax vv dv lat dmax ubi pres hr +#> +#> 1 9434 -1.00 2024-06-21 19:00:00 0 249 8.2 2.7 339 41.7 300 ZARAGOZA… 990 40 +#> 2 9434 -1.00 2024-06-21 20:00:00 0 249 4.8 0.7 8 41.7 358 ZARAGOZA… 990. 46 +#> 3 9434 -1.00 2024-06-21 21:00:00 0 249 3.5 2.1 321 41.7 330 ZARAGOZA… 991. 45 +#> 4 9434 -1.00 2024-06-21 22:00:00 0 249 4.6 3.6 264 41.7 263 ZARAGOZA… 992. 53 +#> 5 9434 -1.00 2024-06-21 23:00:00 0 249 4.1 3 257 41.7 270 ZARAGOZA… 992. 54 +#> 6 9434 -1.00 2024-06-22 00:00:00 0 249 4.7 2.3 262 41.7 288 ZARAGOZA… 992. 55 +#> 7 9434 -1.00 2024-06-22 01:00:00 0 249 4.3 2.6 315 41.7 240 ZARAGOZA… 992. 60 +#> 8 9434 -1.00 2024-06-22 02:00:00 0 249 6.2 5 292 41.7 298 ZARAGOZA… 991. 64 +#> 9 9434 -1.00 2024-06-22 03:00:00 0 249 6.8 4.4 296 41.7 288 ZARAGOZA… 991. 72 +#> 10 9434 -1.00 2024-06-22 04:00:00 0 249 5.5 3.5 305 41.7 293 ZARAGOZA… 991. 76 +#> 11 9434 -1.00 2024-06-22 05:00:00 0 249 5.6 2.5 302 41.7 310 ZARAGOZA… 992. 80 +#> 12 9434 -1.00 2024-06-22 06:00:00 0 249 5.5 4.3 312 41.7 315 ZARAGOZA… 992 78 +#> 13 9434 -1.00 2024-06-22 07:00:00 0 249 7.2 4.9 302 41.7 303 ZARAGOZA… 992. 66 +#> # ℹ 12 more variables: stdvv , ts , pres_nmar , tamin , ta , +#> # tamax , tpr , stddv , inso , tss5cm , pacutp , tss20cm ``` Note that when possible, data representing dates and numbers are converted to diff --git a/vignettes/example-gif.gif b/vignettes/example-gif.gif index 4cf2d871..05156d3b 100644 Binary files a/vignettes/example-gif.gif and b/vignettes/example-gif.gif differ diff --git a/vignettes/extending-climaemet.Rmd b/vignettes/extending-climaemet.Rmd index e50ebe7a..0c47f905 100644 --- a/vignettes/extending-climaemet.Rmd +++ b/vignettes/extending-climaemet.Rmd @@ -197,20 +197,20 @@ db_beach <- read_csv2("https://www.aemet.es/documentos/es/eltiempo/prediccion/pl db_beach #> # A tibble: 591 × 8 -#> ID_PLAYA NOMBRE_PLAYA ID_PROVINCIA NOMBRE_PROVINCIA ID_MUNICIPIO -#> -#> 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 +#> ID_PLAYA NOMBRE_PLAYA ID_PROVINCIA NOMBRE_PROVINCIA ID_MUNICIPIO NOMBRE_MUNICIPIO LATITUD +#> +#> 1 0301101 Raco de l'Albir 03 Alacant/Alicante 03011 l'Alfàs del Pi "38º 3… +#> 2 0301401 Sant Joan / San J… 03 Alacant/Alicante 03014 Alicante/Alacant "38º 2… +#> 3 0301408 El Postiguet 03 Alacant/Alicante 03014 Alicante/Alacant "38º 2… +#> 4 0301410 Saladar 03 Alacant/Alicante 03014 Alicante/Alacant "38º 1… +#> 5 0301808 La Roda 03 Alacant/Alicante 03018 Altea "38º 3… +#> 6 0301809 Cap Blanch 03 Alacant/Alicante 03018 Altea "38º 3… +#> 7 0303102 Llevant / Playa d… 03 Alacant/Alicante 03031 Benidorm "38º 3… +#> 8 0303104 Ponent / Playa de… 03 Alacant/Alicante 03031 Benidorm "38º 3… +#> 9 0304105 Cala Fustera 03 Alacant/Alicante 03041 Benissa "38º 3… +#> 10 0304704 La Fossa 03 Alacant/Alicante 03047 Calp "38º 3… #> # ℹ 581 more rows -#> # ℹ 3 more variables: NOMBRE_MUNICIPIO , LATITUD , LONGITUD +#> # ℹ 1 more variable: LONGITUD ``` Next, we can check the response of the API for a specific case: @@ -228,31 +228,12 @@ api_call <- paste0(api_entry, id_beach) # And we make the call beach_api <- get_data_aemet(api_call) -#> HTTP 429: Límite de peticiones o caudal por minuto excedido para este usuario. Espere al siguiente minuto. Retrying... -#> Waiting 4s for retry backoff ■■■■■■■■■■■ -#> Waiting 4s for retry backoff ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ -#> Waiting 4s for retry backoff ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ -#> Waiting 3s for retry backoff ■■■■■■■■■■■■■■■■■■■■■■■■■ -#> Waiting 3s for retry backoff ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ -#> Waiting 30s for retry backoff ■■■ -#> Waiting 30s for retry backoff ■■■■■■ -#> Waiting 30s for retry backoff ■■■■■■■■■ -#> Waiting 30s for retry backoff ■■■■■■■■■■■■■ -#> Waiting 30s for retry backoff ■■■■■■■■■■■■■■■■ -#> Waiting 30s for retry backoff ■■■■■■■■■■■■■■■■■■■ -#> Waiting 30s for retry backoff ■■■■■■■■■■■■■■■■■■■■■■ -#> Waiting 30s for retry backoff ■■■■■■■■■■■■■■■■■■■■■■■■■ -#> Waiting 30s for retry backoff ■■■■■■■■■■■■■■■■■■■■■■■■■■■■ -#> Waiting 30s for retry backoff ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ -``` - -``` r glimpse(beach_api) #> Rows: 1 #> Columns: 6 #> $ origen -#> $ elaborado "2024-06-20T08:00:20" +#> $ elaborado "2024-06-22T04:50:20" #> $ nombre "Heliopolis" #> $ localidad 12028 #> $ prediccion @@ -274,7 +255,7 @@ glimpse(beach_api$prediccion$dia[[1]]) #> $ sTermica #> $ tAgua #> $ uvMax -#> $ fecha 20240620, 20240621, 20240622 +#> $ fecha 20240622, 20240623, 20240624 #> $ tmaxima #> $ stermica #> $ tagua @@ -307,37 +288,37 @@ glimpse(for_pred_2) #> Rows: 3 #> Columns: 34 #> $ id_beach 1202805, 1202805, 1202805 -#> $ elaborado 2024-06-20 08:00:20, 2024-06-20 08:00:20, 202… -#> $ fecha 2024-06-20, 2024-06-21, 2024-06-22 +#> $ elaborado 2024-06-22 04:50:20, 2024-06-22 04:50:20, 2024-06-22 04:50:20 +#> $ fecha 2024-06-22, 2024-06-23, 2024-06-24 #> $ estadoCielo_value "", "", "" -#> $ estadoCielo_f1 110, 100, 100 -#> $ estadoCielo_descripcion1 "nuboso", "despejado", "despejado" -#> $ estadoCielo_f2 100, 100, 110 -#> $ estadoCielo_descripcion2 "despejado", "despejado", "nuboso" +#> $ estadoCielo_f1 100, 100, 110 +#> $ estadoCielo_descripcion1 "despejado", "despejado", "nuboso" +#> $ estadoCielo_f2 110, 100, 110 +#> $ estadoCielo_descripcion2 "nuboso", "despejado", "nuboso" #> $ viento_value "", "", "" #> $ viento_f1 210, 210, 210 #> $ viento_descripcion1 "flojo", "flojo", "flojo" #> $ viento_f2 210, 210, 210 #> $ viento_descripcion2 "flojo", "flojo", "flojo" #> $ oleaje_value "", "", "" -#> $ oleaje_f1 320, 310, 310 -#> $ oleaje_descripcion1 "moderado", "débil", "débil" +#> $ oleaje_f1 310, 310, 310 +#> $ oleaje_descripcion1 "débil", "débil", "débil" #> $ oleaje_f2 310, 310, 310 #> $ oleaje_descripcion2 "débil", "débil", "débil" #> $ tMaxima_value "", "", "" -#> $ tMaxima_valor1 28, 28, 29 +#> $ tMaxima_valor1 28, 29, 27 #> $ sTermica_value "", "", "" #> $ sTermica_valor1 460, 460, 460 -#> $ sTermica_descripcion1 "calor agradable", "calor agradable", "calor… +#> $ sTermica_descripcion1 "calor agradable", "calor agradable", "calor agradable" #> $ tAgua_value "", "", "" #> $ tAgua_valor1 23, 23, 23 #> $ uvMax_value "", "", "" -#> $ uvMax_valor1 7, 8, 8 +#> $ uvMax_valor1 8, 9, 8 #> $ tmaxima_value "", "", "" -#> $ tmaxima_valor1 28, 28, 29 +#> $ tmaxima_valor1 28, 29, 27 #> $ stermica_value "", "", "" #> $ stermica_valor1 460, 460, 460 -#> $ stermica_descripcion1 "calor agradable", "calor agradable", "calor… +#> $ stermica_descripcion1 "calor agradable", "calor agradable", "calor agradable" #> $ tagua_value "", "", "" #> $ tagua_valor1 23, 23, 23 ``` @@ -384,39 +365,39 @@ aemet_usr__forecast_beach("0301401") %>% #> Rows: 3 #> Columns: 34 #> $ id_beach 301401, 301401, 301401 -#> $ elaborado 2024-06-20 08:00:20, 2024-06-20 08:00:20, 202… -#> $ fecha 2024-06-20, 2024-06-21, 2024-06-22 +#> $ elaborado 2024-06-22 04:50:20, 2024-06-22 04:50:20, 2024-06-22 04:50:20 +#> $ fecha 2024-06-22, 2024-06-23, 2024-06-24 #> $ estadoCielo_value "", "", "" -#> $ estadoCielo_f1 100, 100, 100 -#> $ estadoCielo_descripcion1 "despejado", "despejado", "despejado" +#> $ estadoCielo_f1 100, 120, 110 +#> $ estadoCielo_descripcion1 "despejado", "muy nuboso", "nuboso" #> $ estadoCielo_f2 100, 100, 100 #> $ estadoCielo_descripcion2 "despejado", "despejado", "despejado" #> $ viento_value "", "", "" #> $ viento_f1 210, 210, 210 #> $ viento_descripcion1 "flojo", "flojo", "flojo" -#> $ viento_f2 220, 210, 210 -#> $ viento_descripcion2 "moderado", "flojo", "flojo" +#> $ viento_f2 210, 220, 210 +#> $ viento_descripcion2 "flojo", "moderado", "flojo" #> $ oleaje_value "", "", "" -#> $ oleaje_f1 310, 310, 310 -#> $ oleaje_descripcion1 "débil", "débil", "débil" -#> $ oleaje_f2 310, 320, 310 -#> $ oleaje_descripcion2 "débil", "moderado", "débil" +#> $ oleaje_f1 310, 310, 320 +#> $ oleaje_descripcion1 "débil", "débil", "moderado" +#> $ oleaje_f2 310, 320, 320 +#> $ oleaje_descripcion2 "débil", "moderado", "moderado" #> $ tMaxima_value "", "", "" -#> $ tMaxima_valor1 29, 27, 27 +#> $ tMaxima_valor1 28, 28, 26 #> $ sTermica_value "", "", "" #> $ sTermica_valor1 460, 460, 460 -#> $ sTermica_descripcion1 "calor agradable", "calor agradable", "calor… +#> $ sTermica_descripcion1 "calor agradable", "calor agradable", "calor agradable" #> $ tAgua_value "", "", "" -#> $ tAgua_valor1 23, 23, 23 +#> $ tAgua_valor1 23, 23, 24 #> $ uvMax_value "", "", "" -#> $ uvMax_valor1 8, 9, 8 +#> $ uvMax_valor1 9, 9, 9 #> $ tmaxima_value "", "", "" -#> $ tmaxima_valor1 29, 27, 27 +#> $ tmaxima_valor1 28, 28, 26 #> $ stermica_value "", "", "" #> $ stermica_valor1 460, 460, 460 -#> $ stermica_descripcion1 "calor agradable", "calor agradable", "calor… +#> $ stermica_descripcion1 "calor agradable", "calor agradable", "calor agradable" #> $ tagua_value "", "", "" -#> $ tagua_valor1 23, 23, 23 +#> $ tagua_valor1 23, 23, 24 ``` ``` r @@ -430,38 +411,38 @@ several <- db_beach$ID_PLAYA[7:10] %>% glimpse(several) #> Rows: 12 #> Columns: 34 -#> $ id_beach 303102, 303102, 303102, 303104, 303104, 30310… -#> $ elaborado 2024-06-20 08:00:20, 2024-06-20 08:00:20, 20… -#> $ fecha 2024-06-20, 2024-06-21, 2024-06-22, 2024-06-… +#> $ id_beach 303102, 303102, 303102, 303104, 303104, 303104, 304105, 304105,… +#> $ elaborado 2024-06-22 04:50:20, 2024-06-22 04:50:20, 2024-06-22 04:50:20,… +#> $ fecha 2024-06-22, 2024-06-23, 2024-06-24, 2024-06-22, 2024-06-23, 20… #> $ estadoCielo_value "", "", "", "", "", "", "", "", "", "", "", "" -#> $ estadoCielo_f1 100, 100, 100, 100, 100, 100, 100, 100, 100, … -#> $ estadoCielo_descripcion1 "despejado", "despejado", "despejado", "despe… -#> $ estadoCielo_f2 100, 100, 100, 100, 100, 100, 100, 100, 100, … -#> $ estadoCielo_descripcion2 "despejado", "despejado", "despejado", "despe… +#> $ estadoCielo_f1 100, 120, 110, 100, 120, 110, 100, 120, 120, 100, 120, 120 +#> $ estadoCielo_descripcion1 "despejado", "muy nuboso", "nuboso", "despejado", "muy nuboso",… +#> $ estadoCielo_f2 100, 100, 110, 100, 100, 110, 100, 100, 100, 100, 100, 100 +#> $ estadoCielo_descripcion2 "despejado", "despejado", "nuboso", "despejado", "despejado", "… #> $ viento_value "", "", "", "", "", "", "", "", "", "", "", "" -#> $ viento_f1 210, 210, 210, 210, 210, 210, 210, 210, 210, … -#> $ viento_descripcion1 "flojo", "flojo", "flojo", "flojo", "flojo", … -#> $ viento_f2 220, 220, 210, 220, 220, 210, 220, 210, 220, … -#> $ viento_descripcion2 "moderado", "moderado", "flojo", "moderado", … +#> $ viento_f1 210, 220, 210, 210, 220, 210, 210, 210, 210, 210, 210, 210 +#> $ viento_descripcion1 "flojo", "moderado", "flojo", "flojo", "moderado", "flojo", "fl… +#> $ viento_f2 210, 220, 210, 210, 220, 210, 220, 220, 220, 220, 220, 220 +#> $ viento_descripcion2 "flojo", "moderado", "flojo", "flojo", "moderado", "flojo", "mo… #> $ oleaje_value "", "", "", "", "", "", "", "", "", "", "", "" -#> $ oleaje_f1 320, 320, 310, 320, 320, 310, 310, 310, 310, … -#> $ oleaje_descripcion1 "moderado", "moderado", "débil", "moderado", … -#> $ oleaje_f2 320, 310, 310, 320, 320, 310, 310, 320, 310, … -#> $ oleaje_descripcion2 "moderado", "débil", "débil", "moderado", "mo… +#> $ oleaje_f1 310, 310, 310, 310, 310, 320, 310, 310, 320, 310, 310, 320 +#> $ oleaje_descripcion1 "débil", "débil", "débil", "débil", "débil", "moderado", "débil… +#> $ oleaje_f2 310, 310, 320, 310, 310, 320, 310, 320, 320, 310, 320, 320 +#> $ oleaje_descripcion2 "débil", "débil", "moderado", "débil", "débil", "moderado", "dé… #> $ tMaxima_value "", "", "", "", "", "", "", "", "", "", "", "" -#> $ tMaxima_valor1 25, 27, 26, 26, 27, 26, 28, 28, 28, 27, 28, 28 +#> $ tMaxima_valor1 27, 27, 25, 27, 28, 25, 28, 28, 27, 28, 29, 27 #> $ sTermica_value "", "", "", "", "", "", "", "", "", "", "", "" -#> $ sTermica_valor1 460, 460, 460, 460, 460, 460, 460, 460, 460, … -#> $ sTermica_descripcion1 "calor agradable", "calor agradable", "calor … +#> $ sTermica_valor1 460, 460, 460, 460, 460, 460, 460, 460, 460, 460, 460, 460 +#> $ sTermica_descripcion1 "calor agradable", "calor agradable", "calor agradable", "calor… #> $ tAgua_value "", "", "", "", "", "", "", "", "", "", "", "" -#> $ tAgua_valor1 23, 23, 25, 23, 23, 24, 23, 24, 25, 23, 24, 25 +#> $ tAgua_valor1 23, 23, 24, 23, 24, 24, 24, 25, 24, 24, 25, 24 #> $ uvMax_value "", "", "", "", "", "", "", "", "", "", "", "" -#> $ uvMax_valor1 8, 9, 8, 8, 9, 8, 8, 9, 8, 8, 9, 8 +#> $ uvMax_valor1 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9 #> $ tmaxima_value "", "", "", "", "", "", "", "", "", "", "", "" -#> $ tmaxima_valor1 25, 27, 26, 26, 27, 26, 28, 28, 28, 27, 28, 28 +#> $ tmaxima_valor1 27, 27, 25, 27, 28, 25, 28, 28, 27, 28, 29, 27 #> $ stermica_value "", "", "", "", "", "", "", "", "", "", "", "" -#> $ stermica_valor1 460, 460, 460, 460, 460, 460, 460, 460, 460, … -#> $ stermica_descripcion1 "calor agradable", "calor agradable", "calor … +#> $ stermica_valor1 460, 460, 460, 460, 460, 460, 460, 460, 460, 460, 460, 460 +#> $ stermica_descripcion1 "calor agradable", "calor agradable", "calor agradable", "calor… #> $ tagua_value "", "", "", "", "", "", "", "", "", "", "", "" -#> $ tagua_valor1 23, 23, 25, 23, 23, 24, 23, 24, 25, 23, 24, 25 +#> $ tagua_valor1 23, 23, 24, 23, 24, 24, 24, 25, 24, 24, 25, 24 ```