From 2d0a5e47a9ac6e9afa9e3b5358ffb5b25ba1c746 Mon Sep 17 00:00:00 2001 From: Droomelot De Gendt Date: Tue, 7 Jul 2026 10:26:43 +0200 Subject: [PATCH 1/3] style(R/get.R): apply air formatter and RStudio Reflow Comment to get functions --- R/get.R | 1040 ++++++++++++++++++++++++------------------------------- 1 file changed, 457 insertions(+), 583 deletions(-) diff --git a/R/get.R b/R/get.R index 23e835f..bda9fd5 100644 --- a/R/get.R +++ b/R/get.R @@ -1,206 +1,161 @@ +# DOOCUMENTATION GET LOCS ------------------------------------------------------ #' Get locations from the data warehouse #' #' Returns locations (and optionally, observation wells) from the \emph{Watina} -#' data warehouse that meet -#' several criteria, either as a lazy object or as a -#' local tibble. -#' Criteria refer to spatial or non-spatial physical attributes of the -#' location or the location's observation wells. -#' Essential metadata are included in the result. +#' data warehouse that meet several criteria, either as a lazy object or as a +#' local tibble. Criteria refer to spatial or non-spatial physical attributes of +#' the location or the location's observation wells. Essential metadata are +#' included in the result. #' -#' (TO BE ADDED: Explanation on the different available values of loc_type -#' and loc_validity) +#' (TO BE ADDED: Explanation on the different available values of loc_type and +#' loc_validity) #' #' The lazy object returns a \code{loc_wid} variable, for further use in -#' \emph{remote} queries. -#' However, don't use it in local objects: \code{loc_wid} is not to be -#' regarded as stable. -#' Therefore, \code{collect = TRUE} does not return \code{loc_wid}. -#' -#' The result also provides metadata at the level of the observation -#' well, even when \code{obswells = FALSE}. -#' In the latter case, this refers to the variables -#' \code{soilsurf_ost}, -#' \code{measuringref_ost}, -#' \code{tubelength}, -#' \code{filterlength}, -#' \code{filterdepth}. -#' See the argument \code{obswell_aggr} for options of how to aggregate this -#' information at the location level; -#' by default the latest observation well is used -#' (per location) that meets the criteria on filterdepth. -#' Mind that \code{obswells = FALSE} and \code{filterdepth_na = TRUE} may lead -#' to missing filterdepth values at locations which do have a -#' value for an older observation well, but not for the most recent one. +#' \emph{remote} queries. However, don't use it in local objects: \code{loc_wid} +#' is not to be regarded as stable. Therefore, \code{collect = TRUE} does not +#' return \code{loc_wid}. +#' +#' The result also provides metadata at the level of the observation well, even +#' when \code{obswells = FALSE}. In the latter case, this refers to the +#' variables \code{soilsurf_ost}, \code{measuringref_ost}, \code{tubelength}, +#' \code{filterlength}, \code{filterdepth}. See the argument \code{obswell_aggr} +#' for options of how to aggregate this information at the location level; by +#' default the latest observation well is used (per location) that meets the +#' criteria on filterdepth. Mind that \code{obswells = FALSE} and +#' \code{filterdepth_na = TRUE} may lead to missing filterdepth values at +#' locations which do have a value for an older observation well, but not for +#' the most recent one. #' #' Please note the meaning of observation well in Watina: if there are multiple -#' observation wells attached to one location, these belong to -#' \emph{other timeframes}! -#' So one location always coincides with exactly one observation well at -#' one moment in time. -#' Multiple observation wells can succeed one another because of physical -#' alterations (e.g. damage of a piezometer). -#' Here, the term 'observation well' is used to refer to a fixed installed -#' device in the field (groundwater piezometer, surface water level -#' measurement device). - -#' -#' -#' @param con A \code{DBIConnection} object to Watina. -#' See \code{\link{connect_watina}} to generate one. -#' @param filterdepth_range Numeric vector of length 2. -#' Specifies the allowed range of the depth of the filter below soil -#' surface, as meters (minimum and maximum allowed filterdepth, respectively). -#' This condition is only applied to groundwater piezometers. -#' The second vector element cannot be smaller than the first. -#' Note that 'filterdepth' takes into account \emph{half} the length of the -#' filter. -#' It is always assumed that filters are at the bottom of the tube. -#' Hence -#' \code{filterdepth = tubelength - filterlength / 2 - -#' [tubelength part above soil surface]}. -#' If filterlength is missing, it is assumed to be 0.3 m. -#' With \code{obswells = FALSE}, a location is kept whenever one observation -#' well fulfills the condition. -#' @param filterdepth_guess Logical. -#' Only relevant for groundwater piezometers. -#' Defaults to \code{FALSE}. -#' For observation wells of which tubelength is known, but not -#' the part of the tubelength above soil surface (height of measuring point), -#' filterdepth cannot be calculated and is missing. -#' However, filterdepth will never be larger than tubelength minus half the -#' filterlength; hence a maximum -#' possible (i.e. conservative) value for filterdepth is given by -#' \code{tubelength - filterlength / 2}. -#' With \code{filterdepth_guess = TRUE}, filterdepth is replaced by this value -#' when it cannot be calculated and tubelength is available. -#' This is done before applying the \code{filterdepth_range} condition. -#' To mark these cases, a logical variable \code{filterdepth_guessed} is added -#' to the result: \code{TRUE} for wells where filterdepth was replaced; -#' \code{FALSE} in all other rows. -#' @param filterdepth_na Logical. -#' Are observation wells with missing filterdepth value to be included? -#' Defaults to \code{FALSE}. -#' With \code{filterdepth_guess = TRUE}, this has only effect on the -#' \emph{remaining} observation wells with missing filterdepth value. -#' @param obswells Logical. -#' If \code{TRUE}, the returned object distinguishes all observation wells -#' (see \emph{Details}) that -#' meet the \code{filterdepth_range} condition (or have missing filterdepth, if -#' \code{filterdepth_na = TRUE}). -#' If \code{FALSE} (the default), the returned object just distinguishes -#' locations. -#' In the latter case, the variables \code{obswell_installdate} and -#' \code{obswell_stopdate} are not returned. -#' -#' @param obswell_aggr String. -#' Defines how the attributes of multiple observation wells per location that -#' fulfill the \code{filterdepth_range} and -#' \code{filterdepth_na} criteria (after filterdepth adjustment if -#' \code{filterdepth_guess = TRUE}), are -#' aggregated into one record \strong{per location}: -#' \itemize{ -#' -#' \item \code{"latest"}: return attributes of the most recent observation well -#' that fulfills the \code{filterdepth_range} and -#' \code{filterdepth_na} criteria; -#' -#' \item \code{"latest_fd"}: return attributes of the most recent observation well -#' that fulfills the \code{filterdepth_range} condition, i.e. -#' filterdepth will not be missing unless \emph{all} retained wells have missing -#' filterdepth \emph{and} \code{filterdepth_na = TRUE}; -#' -#' \item \code{"latest_sso"}: return attributes of the most recent observation well -#' that fulfills the \code{filterdepth_range} and -#' \code{filterdepth_na} criteria \emph{and} for which \code{soilsurf_ost} -#' (soil surface level in the -#' \href{http://crs.bkg.bund.de/crseu/crs/eu-description.php?crs_id=Y0JFX09PU1QrJTJGK1VOQ09S}{Ostend height} -#' CRS (EPSG \href{https://epsg.io/5710}{5710}) is not missing (unless -#' \emph{all} retained wells have missing \code{soilsurf_ost}); -#' -#' \item \code{"mean"}: aggregation not by selecting an individual observation -#' well, but by averaging the values of the associated variables -#' \code{soilsurf_ost}, -#' \code{measuringref_ost}, -#' \code{tubelength}, -#' \code{filterlength}, -#' \code{filterdepth} -#' for the observation wells with non-missing values (different -#' wells may be involved for each variable, depending on the distribution of -#' missing values). -#' With \code{filterdepth_guess = TRUE}, the extra variabele -#' \code{filterdepth_guessed} is summarised as \code{TRUE} for a location -#' if at least one of the location's observation wells has -#' \code{filterdepth_guessed = TRUE}. -#' } -#' \strong{In all cases} the returned value of \code{obswell_statecode} and -#' \code{obswell_state} corresponds to the \code{"latest"} approach. -#' The \code{obswell_aggr} argument has no effect on locations with a single -#' retained observation well. -#' It is ignored if \code{obswells = TRUE}. -#' -#' @md -#' -#' @note -#' Up to and including `watina 0.3.0`, the result was sorted according to -#' `area_code` and `loc_code`, -#' both for the lazy query and the collected result. -#' Later versions avoid sorting in case of a lazy result, because -#' otherwise, when using the result inside another lazy query, this led to -#' 'ORDER BY' constructs in SQL subqueries, which must be avoided. -#' If you like to print the lazy object in a sorted manner, you must add -#' `%>% arrange(...)` yourself. -#' -#' @param mask An optional geospatial filter of class \code{sf}. -#' If provided, only locations that intersect with \code{mask} will be returned, -#' with the value of \code{buffer} taken into account. -#' The CRS must be Belgian Lambert 72 (EPSG-code -#' \href{https://epsg.io/31370}{31370}). -#' @param join_mask Logical. -#' Do you want to spatially join the attribute columns of \code{mask} to the -#' resulting tibble? -#' The spatial join is executed with -#' \code{\link[sf:geos_binary_pred]{st_intersects()}} as the topological operator. -#' Beware: if the same location intersects with more than one element of -#' \code{mask} (taking into account the value of \code{buffer}), that location -#' will occur multiple times in the result. -#' \code{join_mask} is ignored if \code{mask} is not provided. -#' @param buffer Number of meters taken as a buffer to enlarge -#' \code{mask} (or shrink it, if \code{buffer < 0}) if \code{mask} is provided. -#' @param bbox Optional geospatial fiter (rectangle). -#' A bounding box (class \code{bbox}), or a vector of four named elements -#' \code{xmin}, \code{xmax}, \code{ymin}, \code{ymax} defining the -#' boundary coordinates of a bounding box. -#' If provided, only locations within this rectangular area will be returned. -#' The CRS must be Belgian Lambert 72 (EPSG-code -#' \href{https://epsg.io/31370}{31370}). -#' @param area_codes An optional vector with area codes. -#' If provided, only locations within the areas will be returned. -#' @param loc_type Type of the location (mainly: the type of measurement device). -#' Defaults to \code{"P"}, i.e. only groundwater piezometers are returned by -#' default. -#' Can be a vector with multiple selected values. -#' @param loc_validity Validation status of the location. -#' Can be a vector with multiple selected values, which must belong to -#' \code{"VLD"}, \code{"ENT"}, \code{"DEL"} or \code{"CLD"}. -#' Defaults to \code{c("VLD", "ENT")}. -#' @param loc_vec An optional vector with location codes. -#' If provided, only locations are returned that are present in this vector. -#' @param collect Should the data be retrieved as a local tibble? -#' If \code{FALSE} (the default), a \code{tbl_lazy} object is returned -#' (lazy query). -#' Hence the result can be further built upon before retrieving data with -#' \code{\link[dplyr:compute]{collect()}}. -#' -#' @return -#' By default, a \code{tbl_lazy} object. -#' With \code{collect = TRUE} or with a specified \code{mask}, -#' a local \code{\link[tibble]{tibble}} is returned. +#' observation wells attached to one location, these belong to \emph{other +#' timeframes}! So one location always coincides with exactly one observation +#' well at one moment in time. Multiple observation wells can succeed one +#' another because of physical alterations (e.g. damage of a piezometer). Here, +#' the term 'observation well' is used to refer to a fixed installed device in +#' the field (groundwater piezometer, surface water level measurement device). +#' +#' +#' @param con A \code{DBIConnection} object to Watina. See +#' \code{\link{connect_watina}} to generate one. +#' @param filterdepth_range Numeric vector of length 2. Specifies the allowed +#' range of the depth of the filter below soil surface, as meters (minimum and +#' maximum allowed filterdepth, respectively). This condition is only applied +#' to groundwater piezometers. The second vector element cannot be smaller +#' than the first. Note that 'filterdepth' takes into account \emph{half} the +#' length of the filter. It is always assumed that filters are at the bottom +#' of the tube. Hence \code{filterdepth = tubelength - filterlength / 2 - +#' [tubelength part above soil surface]}. +#' If filterlength is missing, it is assumed to be 0.3 m. With \code{obswells +#' = FALSE}, a location is kept whenever one observation well fulfills the +#' condition. +#' @param filterdepth_guess Logical. Only relevant for groundwater piezometers. +#' Defaults to \code{FALSE}. For observation wells of which tubelength is +#' known, but not the part of the tubelength above soil surface (height of +#' measuring point), filterdepth cannot be calculated and is missing. However, +#' filterdepth will never be larger than tubelength minus half the +#' filterlength; hence a maximum possible (i.e. conservative) value for +#' filterdepth is given by \code{tubelength - filterlength / 2}. With +#' \code{filterdepth_guess = TRUE}, filterdepth is replaced by this value when +#' it cannot be calculated and tubelength is available. This is done before +#' applying the \code{filterdepth_range} condition. To mark these cases, a +#' logical variable \code{filterdepth_guessed} is added to the result: +#' \code{TRUE} for wells where filterdepth was replaced; \code{FALSE} in all +#' other rows. +#' @param filterdepth_na Logical. Are observation wells with missing filterdepth +#' value to be included? Defaults to \code{FALSE}. With +#' \code{filterdepth_guess = TRUE}, this has only effect on the +#' \emph{remaining} observation wells with missing filterdepth value. +#' @param obswells Logical. If \code{TRUE}, the returned object distinguishes +#' all observation wells (see \emph{Details}) that meet the +#' \code{filterdepth_range} condition (or have missing filterdepth, if +#' \code{filterdepth_na = TRUE}). If \code{FALSE} (the default), the returned +#' object just distinguishes locations. In the latter case, the variables +#' \code{obswell_installdate} and \code{obswell_stopdate} are not returned. +#' @param obswell_aggr String. Defines how the attributes of multiple +#' observation wells per location that fulfill the \code{filterdepth_range} +#' and \code{filterdepth_na} criteria (after filterdepth adjustment if +#' \code{filterdepth_guess = TRUE}), are aggregated into one record +#' \strong{per location}: +#' \itemize{ +#' \item \code{"latest"}: return attributes of the most recent observation +#' well that fulfills the \code{filterdepth_range} and +#' \code{filterdepth_na} criteria; +#' \item \code{"latest_fd"}: return attributes of the most recent observation +#' well that fulfills the \code{filterdepth_range} condition, i.e. +#' filterdepth will not be missing unless \emph{all} retained wells have +#' missing filterdepth \emph{and} \code{filterdepth_na = TRUE}; +#' \item \code{"latest_sso"}: return attributes of the most recent observation +#' well that fulfills the \code{filterdepth_range} and +#' \code{filterdepth_na} criteria \emph{and} for which \code{soilsurf_ost} +#' (soil surface level in the +#' \href{http://crs.bkg.bund.de/crseu/crs/eu-description.php?crs_id=Y0JFX09PU1QrJTJGK1VOQ09S}{Ostend +#' height} CRS (EPSG \href{https://epsg.io/5710}{5710}) is not missing +#' (unless \emph{all} retained wells have missing \code{soilsurf_ost}); +#' \item \code{"mean"}: aggregation not by selecting an individual observation +#' well, but by averaging the values of the associated variables +#' \code{soilsurf_ost}, \code{measuringref_ost}, \code{tubelength}, +#' \code{filterlength}, \code{filterdepth} for the observation wells with +#' non-missing values (different wells may be involved for each variable, +#' depending on the distribution of missing values). With +#' \code{filterdepth_guess = TRUE}, the extra variabele +#' \code{filterdepth_guessed} is summarised as \code{TRUE} for a location +#' if at least one of the location's observation wells has +#' \code{filterdepth_guessed = TRUE}. +#' } +#' \strong{In all cases} the returned value of \code{obswell_statecode} and +#' \code{obswell_state} corresponds to the \code{"latest"} approach. The +#' \code{obswell_aggr} argument has no effect on locations with a single +#' retained observation well. It is ignored if \code{obswells = TRUE}. +#' @param mask An optional geospatial filter of class \code{sf}. If provided, +#' only locations that intersect with \code{mask} will be returned, with the +#' value of \code{buffer} taken into account. The CRS must be Belgian Lambert +#' 72 (EPSG-code \href{https://epsg.io/31370}{31370}). +#' @param join_mask Logical. Do you want to spatially join the attribute columns +#' of \code{mask} to the resulting tibble? The spatial join is executed with +#' \code{\link[sf:geos_binary_pred]{st_intersects()}} as the topological +#' operator. Beware: if the same location intersects with more than one +#' element of \code{mask} (taking into account the value of \code{buffer}), +#' that location will occur multiple times in the result. \code{join_mask} is +#' ignored if \code{mask} is not provided. +#' @param buffer Number of meters taken as a buffer to enlarge \code{mask} (or +#' shrink it, if \code{buffer < 0}) if \code{mask} is provided. +#' @param bbox Optional geospatial fiter (rectangle). A bounding box (class +#' \code{bbox}), or a vector of four named elements \code{xmin}, \code{xmax}, +#' \code{ymin}, \code{ymax} defining the boundary coordinates of a bounding +#' box. If provided, only locations within this rectangular area will be +#' returned. The CRS must be Belgian Lambert 72 (EPSG-code +#' \href{https://epsg.io/31370}{31370}). +#' @param area_codes An optional vector with area codes. If provided, only +#' locations within the areas will be returned. +#' @param loc_type Type of the location (mainly: the type of measurement +#' device). Defaults to \code{"P"}, i.e. only groundwater piezometers are +#' returned by default. Can be a vector with multiple selected values. +#' @param loc_validity Validation status of the location. Can be a vector with +#' multiple selected values, which must belong to \code{"VLD"}, \code{"ENT"}, +#' \code{"DEL"} or \code{"CLD"}. Defaults to \code{c("VLD", "ENT")}. +#' @param loc_vec An optional vector with location codes. If provided, only +#' locations are returned that are present in this vector. +#' @param collect Should the data be retrieved as a local tibble? If +#' \code{FALSE} (the default), a \code{tbl_lazy} object is returned (lazy +#' query). Hence the result can be further built upon before retrieving data +#' with \code{\link[dplyr:compute]{collect()}}. +#' +#' @return By default, a \code{tbl_lazy} object. With \code{collect = TRUE} or +#' with a specified \code{mask}, a local \code{\link[tibble]{tibble}} is +#' returned. #' #' (TO BE ADDED: Explanation on the variable names of the returned object) #' #' @family functions to query the data warehouse #' +#' @md +#' @note Up to and including `watina 0.3.0`, the result was sorted according to +#' `area_code` and `loc_code`, both for the lazy query and the collected result. +#' Later versions avoid sorting in case of a lazy result, because otherwise, +#' when using the result inside another lazy query, this led to 'ORDER BY' +#' constructs in SQL subqueries, which must be avoided. If you like to print the +#' lazy object in a sorted manner, you must add `%>% arrange(...)` yourself. +#' #' @examples #' \dontrun{ #' watina <- connect_watina() @@ -329,42 +284,32 @@ #' #' @export #' @importFrom rlang .data -#' @importFrom assertthat -#' assert_that -#' is.number -#' is.flag -#' noNA -#' @importFrom dplyr -#' %>% -#' tbl -#' filter -#' left_join -#' select -#' distinct -#' arrange -#' group_by -#' ungroup -#' sql -get_locs <- function(con, - filterdepth_range = c(0, 3), - filterdepth_guess = FALSE, - filterdepth_na = FALSE, - obswells = FALSE, - obswell_aggr = c( - "latest", - "latest_fd", - "latest_sso", - "mean" - ), - mask = NULL, - join_mask = FALSE, - buffer = 10, - bbox = NULL, - area_codes = NULL, - loc_type = c("P", "S", "R", "N", "W", "D", "L", "B"), - loc_validity = c("VLD", "ENT"), - loc_vec = NULL, - collect = FALSE) { +#' @importFrom assertthat assert_that is.number is.flag noNA +#' @importFrom dplyr %>% tbl filter left_join select distinct arrange group_by +#' ungroup sql +# FUNCTION GET LOCS ------------------------------------------------------------ +get_locs <- function( + con, + filterdepth_range = c(0, 3), + filterdepth_guess = FALSE, + filterdepth_na = FALSE, + obswells = FALSE, + obswell_aggr = c( + "latest", + "latest_fd", + "latest_sso", + "mean" + ), + mask = NULL, + join_mask = FALSE, + buffer = 10, + bbox = NULL, + area_codes = NULL, + loc_type = c("P", "S", "R", "N", "W", "D", "L", "B"), + loc_validity = c("VLD", "ENT"), + loc_vec = NULL, + collect = FALSE +) { assert_that( is.numeric(filterdepth_range), length(filterdepth_range) == 2, @@ -390,7 +335,9 @@ get_locs <- function(con, obswell_aggr <- match.arg(obswell_aggr) if (!is.null(mask) & !collect) { - message("As a mask always invokes a collect(), the argument 'collect = FALSE' will be ignored.") + message( + "As a mask always invokes a collect(), the argument 'collect = FALSE' will be ignored." + ) } if (!is.null(mask)) { @@ -477,19 +424,18 @@ get_locs <- function(con, left_join( tbl(con, "vwDimPeilpunt") %>% filter( - .data$PeilpuntStatusCode %in% c( - "VLD", - "ENT", - "CLD" - ), + .data$PeilpuntStatusCode %in% + c( + "VLD", + "ENT", + "CLD" + ), .data$PeilpuntOpenbaarheidTypeCode == "PLME", .data$PeilpuntOpenbaarheidCode == "UNKWN" ) %>% mutate( - PeilpuntPlaatsing = - sql("CAST(PeilpuntPlaatsing AS date)"), - PeilpuntStopzetting = - sql("CAST(PeilpuntStopzetting AS date)") + PeilpuntPlaatsing = sql("CAST(PeilpuntPlaatsing AS date)"), + PeilpuntStopzetting = sql("CAST(PeilpuntStopzetting AS date)") ), by = "MeetpuntWID" ) %>% @@ -507,9 +453,8 @@ get_locs <- function(con, filterdepth = .data$tubelength - .data$ReferentieNiveauMaaiveld - .data$filterlength / 2, - soilsurf_ost = - .data$ReferentieNiveauTAW - - .data$ReferentieNiveauMaaiveld + soilsurf_ost = .data$ReferentieNiveauTAW - + .data$ReferentieNiveauMaaiveld ) %>% select( loc_wid = .data$MeetpuntWID, @@ -539,8 +484,8 @@ get_locs <- function(con, locs <- locs %>% mutate( - filterdepth_guessed = - is.na(.data$filterdepth) & !is.na(.data$tubelength), + filterdepth_guessed = is.na(.data$filterdepth) & + !is.na(.data$tubelength), filterdepth = ifelse( .data$filterdepth_guessed == 1, # (sql: logical stored as bit) @@ -578,114 +523,99 @@ get_locs <- function(con, mutate( obswell_count = n(), obswell_maxrank = max(.data$obswell_rank, na.rm = TRUE), - obswell_maxrank_fd = - max( - ifelse( - is.na(.data$filterdepth), - NA, - .data$obswell_rank - ), - na.rm = TRUE + obswell_maxrank_fd = max( + ifelse( + is.na(.data$filterdepth), + NA, + .data$obswell_rank ), - obswell_maxrank_sso = - max( - ifelse( - is.na(.data$soilsurf_ost), - NA, - .data$obswell_rank - ), - na.rm = TRUE + na.rm = TRUE + ), + obswell_maxrank_sso = max( + ifelse( + is.na(.data$soilsurf_ost), + NA, + .data$obswell_rank ), - obswell_statecode = - max( - ifelse( - .data$obswell_rank == - .data$obswell_maxrank, - .data$obswell_statecode, - NA - ), - na.rm = TRUE + na.rm = TRUE + ), + obswell_statecode = max( + ifelse( + .data$obswell_rank == .data$obswell_maxrank, + .data$obswell_statecode, + NA ), - obswell_state = - max( - ifelse( - .data$obswell_rank == - .data$obswell_maxrank, - .data$obswell_state, - NA - ), - na.rm = TRUE - ) + na.rm = TRUE + ), + obswell_state = max( + ifelse( + .data$obswell_rank == .data$obswell_maxrank, + .data$obswell_state, + NA + ), + na.rm = TRUE + ) ) locs <- switch( obswell_aggr, - "latest" = - locs %>% - ungroup() %>% - filter( - .data$obswell_count == 1 | - .data$obswell_rank == .data$obswell_maxrank - ), - "latest_fd" = - locs %>% - ungroup() %>% - filter( - .data$obswell_count == 1 | - (.data$obswell_rank == - .data$obswell_maxrank_fd) | - (is.na(.data$obswell_maxrank_fd) & - (.data$obswell_rank == - .data$obswell_maxrank)) - ), - "latest_sso" = - locs %>% - ungroup() %>% - filter( - .data$obswell_count == 1 | - (.data$obswell_rank == - .data$obswell_maxrank_sso) | - (is.na(.data$obswell_maxrank_sso) & - (.data$obswell_rank == - .data$obswell_maxrank)) - ), - "mean" = - locs %>% - mutate( - soilsurf_ost = mean(.data$soilsurf_ost, na.rm = TRUE), - measuringref_ost = mean(.data$measuringref_ost, na.rm = TRUE), - filterdepth = mean(.data$filterdepth, na.rm = TRUE), - filterlength = mean(.data$filterlength, na.rm = TRUE), - tubelength = mean(.data$tubelength, na.rm = TRUE) - ) %>% - { - if ("filterdepth_guessed" %in% colnames(.)) { + "latest" = locs %>% + ungroup() %>% + filter( + .data$obswell_count == 1 | + .data$obswell_rank == .data$obswell_maxrank + ), + "latest_fd" = locs %>% + ungroup() %>% + filter( + .data$obswell_count == 1 | + (.data$obswell_rank == .data$obswell_maxrank_fd) | + (is.na(.data$obswell_maxrank_fd) & + (.data$obswell_rank == .data$obswell_maxrank)) + ), + "latest_sso" = locs %>% + ungroup() %>% + filter( + .data$obswell_count == 1 | + (.data$obswell_rank == .data$obswell_maxrank_sso) | + (is.na(.data$obswell_maxrank_sso) & + (.data$obswell_rank == .data$obswell_maxrank)) + ), + "mean" = locs %>% + mutate( + soilsurf_ost = mean(.data$soilsurf_ost, na.rm = TRUE), + measuringref_ost = mean(.data$measuringref_ost, na.rm = TRUE), + filterdepth = mean(.data$filterdepth, na.rm = TRUE), + filterlength = mean(.data$filterlength, na.rm = TRUE), + tubelength = mean(.data$tubelength, na.rm = TRUE) + ) %>% + { + if ("filterdepth_guessed" %in% colnames(.)) { + mutate( + ., + filterdepth_guessed = max( + ifelse( + .data$filterdepth_guessed == 1, + # (sql: logical stored as bit) + 1, + 0 + ), + na.rm = TRUE + ) + ) %>% mutate( - ., - filterdepth_guessed = - max( - ifelse( - .data$filterdepth_guessed == 1, - # (sql: logical stored as bit) - 1, - 0 - ), - na.rm = TRUE - ) - ) %>% - mutate( - filterdepth_guessed = sql("CAST(filterdepth_guessed AS bit)") - ) - } else { - . - } - } %>% - ungroup() %>% - filter( - .data$obswell_count == 1 | - .data$obswell_rank == .data$obswell_maxrank - ) + filterdepth_guessed = sql("CAST(filterdepth_guessed AS bit)") + ) + } else { + . + } + } %>% + ungroup() %>% + filter( + .data$obswell_count == 1 | + .data$obswell_rank == .data$obswell_maxrank + ) ) %>% select( -.data$obswell_code, @@ -768,79 +698,66 @@ get_locs <- function(con, return(locs) } - +# DOOCUMENTATION GET XG3 ------------------------------------------------------- #' Get XG3 values from the data warehouse #' -#' Returns XG3 values from the \emph{Watina} data warehouse, -#' either as a lazy object or as a -#' local tibble. -#' The values must belong to selected locations -#' and +#' Returns XG3 values from the \emph{Watina} data warehouse, either as a lazy +#' object or as a local tibble. The values must belong to selected locations and #' to a specified timeframe. #' -#' The timeframe is a selection interval between -#' a given first and last hydroyear. +#' The timeframe is a selection interval between a given first and last +#' hydroyear. #' #' Note: the arguments \code{truncated} and \code{with_estimated} are currently -#' not used. -#' Currently, non-truncated values are returned, with usage of estimated values. +#' not used. Currently, non-truncated values are returned, with usage of +#' estimated values. #' -#' (TO BE ADDED: What are XG3 values? What is a hydroyear? -#' Why truncate, and why truncate by default? -#' When to choose which \code{vert_crs}?) -#' -#' @md -#' -#' @note -#' Up to and including `watina 0.3.0`, the result was sorted according to -#' `loc_code` and `hydroyear`, both for the lazy query and the -#' collected result. -#' Later versions avoid sorting in case of a lazy result, because -#' otherwise, when using the result inside another lazy query, this led to -#' 'ORDER BY' constructs in SQL subqueries, which must be avoided. -#' If you like to print the lazy object in a sorted manner, you must add -#' `%>% arrange(...)` yourself. +#' (TO BE ADDED: What are XG3 values? What is a hydroyear? Why truncate, and why +#' truncate by default? When to choose which \code{vert_crs}?) #' #' @param locs A \code{tbl_lazy} object or a data frame, with at least a column -#' \code{loc_code} that defines the locations for which values are to be -#' returned. -#' Typically, this will be the object returned by \code{\link{get_locs}}. +#' \code{loc_code} that defines the locations for which values are to be +#' returned. Typically, this will be the object returned by +#' \code{\link{get_locs}}. #' @param startyear First hydroyear of the timeframe. #' @param endyear Last hydroyear of the timeframe. #' @param vert_crs A string, defining the 1-dimensional vertical coordinate -#' reference system (CRS) of the XG3 water levels. -#' Either \code{"local"} (the default, i.e. returned values are relative to -#' soil surface level, with positive values = above soil surface), -#' or \code{"ostend"} (values are from the CRS -#' \href{http://crs.bkg.bund.de/crseu/crs/eu-description.php?crs_id=Y0JFX09PU1QrJTJGK1VOQ09S}{Ostend height} -#' (EPSG \href{https://epsg.io/5710}{5710}), -#' also known as 'TAW' or 'DNG'), -#' or \code{"both"}, where the values for both CRS options are returned. -#' The units are always meters. -#' @param truncated Logical. -#' If \code{TRUE} (the default), the XG3 values are calculated after having set -#' the underlying water level measurements that are above soil surface level -#' to the soil surface level itself -#' (which is zero in the case of the local CRS). -#' @param with_estimated Logical. -#' If \code{TRUE} (the default), the XG3 values calculations also use estimated -#' (i.e. non-measured) water level data that are available in the data warehouse. +#' reference system (CRS) of the XG3 water levels. Either \code{"local"} (the +#' default, i.e. returned values are relative to soil surface level, with +#' positive values = above soil surface), or \code{"ostend"} (values are from +#' the CRS +#' \href{http://crs.bkg.bund.de/crseu/crs/eu-description.php?crs_id=Y0JFX09PU1QrJTJGK1VOQ09S}{Ostend +#' height} (EPSG \href{https://epsg.io/5710}{5710}), also known as 'TAW' or +#' 'DNG'), or \code{"both"}, where the values for both CRS options are +#' returned. The units are always meters. +#' @param truncated Logical. If \code{TRUE} (the default), the XG3 values are +#' calculated after having set the underlying water level measurements that +#' are above soil surface level to the soil surface level itself (which is +#' zero in the case of the local CRS). +#' @param with_estimated Logical. If \code{TRUE} (the default), the XG3 values +#' calculations also use estimated (i.e. non-measured) water level data that +#' are available in the data warehouse. #' #' @inheritParams get_locs #' -#' @return -#' By default, a \code{tbl_lazy} object. -#' With \code{collect = TRUE}, -#' a local \code{\link[tibble]{tibble}} is returned. +#' @return By default, a \code{tbl_lazy} object. With \code{collect = TRUE}, a +#' local \code{\link[tibble]{tibble}} is returned. #' #' (TO BE ADDED: Explanation on the variable names of the returned object) #' -#' The suffix of the XG3 variables is either "\code{_lcl}" for -#' \code{vert_crs = "local"} or -#' "\code{_ost}" for \code{vert_crs = "ostend"}. +#' The suffix of the XG3 variables is either "\code{_lcl}" for \code{vert_crs = +#' "local"} or "\code{_ost}" for \code{vert_crs = "ostend"}. #' #' @family functions to query the data warehouse #' +#' @md +#' @note Up to and including `watina 0.3.0`, the result was sorted according to +#' `loc_code` and `hydroyear`, both for the lazy query and the collected result. +#' Later versions avoid sorting in case of a lazy result, because otherwise, +#' when using the result inside another lazy query, this led to 'ORDER BY' +#' constructs in SQL subqueries, which must be avoided. If you like to print the +#' lazy object in a sorted manner, you must add `%>% arrange(...)` yourself. +#' #' @examples #' \dontrun{ #' watina <- connect_watina() @@ -870,33 +787,22 @@ get_locs <- function(con, #' } #' #' @export -#' @importFrom assertthat -#' assert_that -#' is.number -#' is.flag -#' noNA +#' @importFrom assertthat assert_that is.number is.flag noNA #' @importFrom rlang .data -#' @importFrom lubridate -#' year -#' now -#' @importFrom dplyr -#' %>% -#' copy_to -#' filter -#' left_join -#' inner_join -#' select -#' contains -#' arrange -#' distinct -get_xg3 <- function(locs, - con, - startyear, - endyear = year(now()) - 1, - vert_crs = c("local", "ostend", "both"), - truncated = TRUE, - with_estimated = TRUE, - collect = FALSE) { +#' @importFrom lubridate year now +#' @importFrom dplyr %>% copy_to filter left_join inner_join select contains +#' arrange distinct +# FUNCTION GET XG3 ------------------------------------------------------------- +get_xg3 <- function( + locs, + con, + startyear, + endyear = year(now()) - 1, + vert_crs = c("local", "ostend", "both"), + truncated = TRUE, + with_estimated = TRUE, + collect = FALSE +) { vert_crs <- match.arg(vert_crs) assert_that(is.number(startyear)) assert_that(is.number(endyear)) @@ -973,7 +879,8 @@ get_xg3 <- function(locs, select(-.data$loc_wid) xg3 <- - switch(vert_crs, + switch( + vert_crs, local = xg3 %>% select(-contains("ost")), ostend = xg3 %>% select(-contains("lcl")), both = xg3 @@ -992,47 +899,42 @@ get_xg3 <- function(locs, return(xg3) } - +# DOOCUMENTATION GET CHEM ------------------------------------------------------ #' Get hydrochemical data from the data warehouse #' -#' Returns hydrochemical data from the \emph{Watina} data warehouse, -#' either as a lazy object or as a -#' local tibble. -#' The values must belong to selected locations -#' and -#' to a specified timeframe. +#' Returns hydrochemical data from the \emph{Watina} data warehouse, either as a +#' lazy object or as a local tibble. The values must belong to selected +#' locations and to a specified timeframe. #' -#' The timeframe is a selection interval between -#' a given \code{startdate} and \code{enddate}. +#' The timeframe is a selection interval between a given \code{startdate} and +#' \code{enddate}. #' -#' The water samples must meet a specified electroneutrality -#' condition, set by \code{en_range}. +#' The water samples must meet a specified electroneutrality condition, set by +#' \code{en_range}. #' #' \itemize{ #' \item This condition is however ignored when the sample's iron (meq/l) / -#' conductivity (µS/cm) ratio exceeds \code{en_fecond_threshold} (use -#' \code{en_fecond_threshold = NA} if you don't want this to happen). +#' conductivity (µS/cm) ratio exceeds \code{en_fecond_threshold} (use +#' \code{en_fecond_threshold = NA} if you don't want this to happen). #' \item Further, water samples are included by default if their -#' electroneutrality is \code{NA} (this is controlled by the -#' \code{en_exclude_na} argument). +#' electroneutrality is \code{NA} (this is controlled by the +#' \code{en_exclude_na} argument). #' \item Finally, please note that measurements of non-ion variables are -#' \emph{always} returned! +#' \emph{always} returned! #' } #' To retrieve all data from all water samples, use \code{en_range = c(-1, 1)}. #' #' **More information about the electroneutrality** #' -#' We expect groundwater samples to have no net charge, i.e. the total -#' positive charge from cations must equal the total negative charge -#' from anions. -#' To ensure this is true (if we ignore the inevitable margin of error -#' in the laboratory), -#' we calculate: +#' We expect groundwater samples to have no net charge, i.e. the total positive +#' charge from cations must equal the total negative charge from anions. To +#' ensure this is true (if we ignore the inevitable margin of error in the +#' laboratory), we calculate: #' \itemize{ #' \item the sum of charges from anions (AN) in the sample as -#' *HCO3 + SO4 + PO4 + Cl + NO3 + NO2* +#' *HCO3 + SO4 + PO4 + Cl + NO3 + NO2* #' \item the sum of charges from cations (CAT) in the sample as -#' *Ca + Mg + Na + K + Fe + NH4* +#' *Ca + Mg + Na + K + Fe + NH4* #' } #' #' Then we derive the electroneutrality as *(CAT - AN)/(CAT + AN)* @@ -1042,103 +944,76 @@ get_xg3 <- function(locs, #' that were not included in the analysis. #' #' The \code{get_chem()} function allows for a standard tolerance of +/-0.1 for -#' the electroneutrality. -#' This value can be adapted using the \code{en_range} argument. -#' -#' @md -#' -#' @note -#' Up to and including `watina 0.3.0`, the result was sorted according to -#' `loc_code`, `date` and `chem_variable`, both for the lazy query and the -#' collected result. -#' Later versions avoid sorting in case of a lazy result, because -#' otherwise, when using the result inside another lazy query, this led to -#' 'ORDER BY' constructs in SQL subqueries, which must be avoided. -#' If you like to print the lazy object in a sorted manner, you must add -#' `%>% arrange(...)` yourself. -#' -#' @param startdate First date of the timeframe, as a string. -#' The string must use a formatting of the order 'day month year', -#' i.e. a format which can be interpreted by \code{\link[lubridate:ymd]{dmy}}. -#' -#' Examples: -#' \code{"16-1-2005"}, -#' \code{"16-01-2005"}, -#' \code{"1-01-2005"}, -#' \code{"16/1/2005"}, -#' \code{"16/1/05"}, -#' \code{"16/1/88"} (years 69 and higher are regarded as 19xy), -#' \code{"16/1-2005"}, -#' \code{"23 Oct 99"}, -#' \code{"23 Okt 99"} (supposing this notation follows your system locale), -#' \code{"16 1-!!-2005"}, -#' ...... -#' @param enddate Last date of the timeframe, as a string. -#' The same formatting rule must be applied as in \code{startdate}. -#' Defaults to a string representation of the current system date. -#' @param conc_type A string defining the type of concentration in -#' \emph{ionic concentration variables}. -#' Either: +#' the electroneutrality. This value can be adapted using the \code{en_range} +#' argument. +#' +#' @param startdate First date of the timeframe, as a string. The string must +#' use a formatting of the order 'day month year', i.e. a format which can be +#' interpreted by \code{\link[lubridate:ymd]{dmy}}. +#' +#' Examples: \code{"16-1-2005"}, \code{"16-01-2005"}, \code{"1-01-2005"}, +#' \code{"16/1/2005"}, \code{"16/1/05"}, \code{"16/1/88"} (years 69 and higher +#' are regarded as 19xy), \code{"16/1-2005"}, \code{"23 Oct 99"}, \code{"23 +#' Okt 99"} (supposing this notation follows your system locale), \code{"16 +#' 1-!!-2005"}, ...... +#' @param enddate Last date of the timeframe, as a string. The same formatting +#' rule must be applied as in \code{startdate}. Defaults to a string +#' representation of the current system date. +#' @param conc_type A string defining the type of concentration in \emph{ionic +#' concentration variables}. Either: #' \itemize{ #' \item{\code{"mass"}:} mass concentration (the default); #' \item{\code{"eq"}:} equivalent concentration (= normality), referring to the -#' electrical charge of the dissolved ion's main natural form. -#' } -#' Note that the argument has no effect on the value of non-ion-variables. -#' @param en_range Numeric vector of length 2. -#' Specifies the allowed range of -#' water sample electroneutrality for ion-variable measurements (see Details). -#' Both vector elements must be within the range \code{c(-1, 1)}, with the -#' second element not being smaller than the first. -#' Note that this argument only affects the selection of water samples for -#' ionic concentration variables, not for non-ion variables such as pH and -#' electrical conductivity. -#' Measurements of non-ion variables are always returned. -#' @param en_exclude_na Logical. -#' Should ion-variable measurements of water samples with missing -#' electroneutrality value be omitted? -#' Defaults to FALSE. -#' A missing electroneutrality value is the consequence of one or more missing -#' values of ionic concentration variables that are needed for -#' electroneutrality calculation of the water sample. -#' Note that this argument has no effect on the selection of non-ion variable -#' measurements, which are always returned. -#' @param en_fecond_threshold A number (with a sensible default). -#' May be set to \code{NA} or \code{NULL} by the user. -#' \itemize{ -#' \item If \code{en_fecond_threshold} is a number (numeric scalar), all -#' measurements from water samples with an iron (meq/l) / -#' conductivity (µS/cm) ratio -#' (\code{Fe/CondL}) equal to or larger than \code{en_fecond_threshold} are -#' returned, regardless of the \code{en_range} and \code{en_exclude_na} -#' arguments. -#' \item If \code{en_fecond_threshold} is set to \code{NA} or \code{NULL}, -#' the iron / conductivity ratio is ignored. -#' Hence, no exceptions are made to -#' the conditions imposed by \code{en_range} and \code{en_exclude_na} -#' (except for measurements of non-ion variables, which are always returned). +#' electrical charge of the dissolved ion's main natural form. #' } +#' Note that the argument has no effect on the value of non-ion-variables. +#' @param en_range Numeric vector of length 2. Specifies the allowed range of +#' water sample electroneutrality for ion-variable measurements (see Details). +#' Both vector elements must be within the range \code{c(-1, 1)}, with the +#' second element not being smaller than the first. Note that this argument +#' only affects the selection of water samples for ionic concentration +#' variables, not for non-ion variables such as pH and electrical +#' conductivity. Measurements of non-ion variables are always returned. +#' @param en_exclude_na Logical. Should ion-variable measurements of water +#' samples with missing electroneutrality value be omitted? Defaults to FALSE. +#' A missing electroneutrality value is the consequence of one or more missing +#' values of ionic concentration variables that are needed for +#' electroneutrality calculation of the water sample. Note that this argument +#' has no effect on the selection of non-ion variable measurements, which are +#' always returned. +#' @param en_fecond_threshold A number (with a sensible default). May be set to +#' \code{NA} or \code{NULL} by the user. +#' \itemize{ +#' \item If \code{en_fecond_threshold} is a number (numeric scalar), all +#' measurements from water samples with an iron (meq/l) / conductivity +#' (µS/cm) ratio (\code{Fe/CondL}) equal to or larger than +#' \code{en_fecond_threshold} are returned, regardless of the +#' \code{en_range} and \code{en_exclude_na} arguments. +#' \item If \code{en_fecond_threshold} is set to \code{NA} or \code{NULL}, the +#' iron / conductivity ratio is ignored. Hence, no exceptions are made to +#' the conditions imposed by \code{en_range} and \code{en_exclude_na} +#' (except for measurements of non-ion variables, which are always +#' returned). +#' } #' #' @inheritParams get_xg3 #' -#' @return -#' By default, a \code{tbl_lazy} object. -#' With \code{collect = TRUE}, -#' a local \code{\link[tibble]{tibble}} is returned. +#' @return By default, a \code{tbl_lazy} object. With \code{collect = TRUE}, a +#' local \code{\link[tibble]{tibble}} is returned. #' #' **Returned Fields** #' #' - `loc_code` (chr): location code such as KESP001, ABES001, ... #' - `date` (Date): sampling date -#' - `lab_project_id` (chr): code or identifier of the project as used -#' by the laboratory -#' - `lab_sample_id` (chr): code or identifier of the sample as used -#' by the laboratory +#' - `lab_project_id` (chr): code or identifier of the project as used by the +#' laboratory +#' - `lab_sample_id` (chr): code or identifier of the sample as used by the +#' laboratory #' - `chem_variable` (chr): abbreviation for the chemical variable (detailed below) #' - `value` (num): measurement value #' - `unit` (chr): unit -#' - `below_loq` (logi): is the value below the limit of quantitation -#' for this analysis in the laboratory? +#' - `below_loq` (logi): is the value below the limit of quantitation for this +#' analysis in the laboratory? #' - `loq` (num): limit of quantitation for this analysis in the laboratory #' - `elneutr` (num): value of the calculated electroneutrality (not in %) #' @@ -1166,6 +1041,15 @@ get_xg3 <- function(locs, #' #' @family functions to query the data warehouse #' +#' @md +#' @note Up to and including `watina 0.3.0`, the result was sorted according to +#' `loc_code`, `date` and `chem_variable`, both for the lazy query and the +#' collected result. Later versions avoid sorting in case of a lazy result, +#' because otherwise, when using the result inside another lazy query, this led +#' to 'ORDER BY' constructs in SQL subqueries, which must be avoided. If you +#' like to print the lazy object in a sorted manner, you must add `%>% +#' arrange(...)` yourself. +#' #' @examples #' \dontrun{ #' watina <- connect_watina() @@ -1218,45 +1102,27 @@ get_xg3 <- function(locs, #' } #' #' @export -#' @importFrom assertthat -#' assert_that -#' is.number -#' is.flag -#' noNA -#' is.date +#' @importFrom assertthat assert_that is.number is.flag noNA is.date #' @importFrom rlang .data -#' @importFrom lubridate -#' dmy -#' today -#' day -#' month -#' year -#' @importFrom dplyr -#' %>% -#' copy_to -#' filter -#' left_join -#' inner_join -#' select -#' contains -#' arrange -#' distinct -#' sql -#' rename -#' between -get_chem <- function(locs, - con, - startdate, - enddate = paste( - day(today()), - month(today()), - year(today()) - ), - conc_type = c("mass", "eq"), - en_range = c(-0.1, 0.1), - en_exclude_na = FALSE, - en_fecond_threshold = 0.0023, - collect = FALSE) { +#' @importFrom lubridate dmy today day month year +#' @importFrom dplyr %>% copy_to filter left_join inner_join select contains +#' arrange distinct sql rename between +# FUNCTION GET CHEM ------------------------------------------------------------ +get_chem <- function( + locs, + con, + startdate, + enddate = paste( + day(today()), + month(today()), + year(today()) + ), + conc_type = c("mass", "eq"), + en_range = c(-0.1, 0.1), + en_exclude_na = FALSE, + en_fecond_threshold = 0.0023, + collect = FALSE +) { conc_type <- match.arg(conc_type) assert_that( @@ -1403,28 +1269,31 @@ get_chem <- function(locs, ) %>% filter(!is.na(.data$value_mass)) %>% # empty rows occur in the DWH! mutate( - provide_eq_unit = # when are value_eq units effectively meq/l ? - sql( - "CAST((CASE + # when are value_eq units effectively meq/l ? + provide_eq_unit = sql( + "CAST((CASE WHEN chem_variable IN ('P-PO4', 'N-NO3', 'N-NO2', 'N-NH4', 'HCO3', 'SO4', 'Cl', 'Na', 'K', 'Ca', 'Mg', 'Fe', 'Mn', 'Si', 'Al') THEN 1 ELSE 0 END) AS bit)" - ) + ) ) # preparing for the application of the en_fecond_threshold: if (!is.na(en_fecond_threshold) & !is.null(en_fecond_threshold)) { - if (any( - chemdata %>% - filter( - .data$ChemVarCode == "CondL", - !is.na(.data$MeetwaardeMEQ) - ) %>% - pull(.data$MeetwaardeMEQ) == 0 - )) { + if ( + any( + chemdata %>% + filter( + .data$ChemVarCode == "CondL", + !is.na(.data$MeetwaardeMEQ) + ) %>% + pull(.data$MeetwaardeMEQ) == + 0 + ) + ) { warning( "Zeroes for 'CondL' (lab conductivity) detected. ", "These rows will be ignored in calculating the iron / conductivity ", @@ -1469,7 +1338,8 @@ get_chem <- function(locs, # I.1 applying the en_range condition: chem %>% filter( - (!is.na(.data$elneutr) & between(.data$elneutr, !!en_range[1], !!en_range[2])) | + (!is.na(.data$elneutr) & + between(.data$elneutr, !!en_range[1], !!en_range[2])) | .data$provide_eq_unit == "FALSE" ) } else { @@ -1477,7 +1347,8 @@ get_chem <- function(locs, chem %>% left_join(samples_fecond, by = "lab_sample_id") %>% filter( - (!is.na(.data$elneutr) & between(.data$elneutr, !!en_range[1], !!en_range[2])) | + (!is.na(.data$elneutr) & + between(.data$elneutr, !!en_range[1], !!en_range[2])) | .data$fecond >= en_fecond_threshold | .data$provide_eq_unit == "FALSE" ) %>% @@ -1508,16 +1379,19 @@ get_chem <- function(locs, } chem <- - switch(conc_type, + switch( + conc_type, mass = chem %>% rename(value = .data$value_mass), eq = chem %>% rename(value = .data$value_eq) %>% - mutate(unit = ifelse( - .data$provide_eq_unit == "TRUE", - "meq/l", - .data$unit - )) + mutate( + unit = ifelse( + .data$provide_eq_unit == "TRUE", + "meq/l", + .data$unit + ) + ) ) %>% select(-contains("value_"), -.data$provide_eq_unit) %>% mutate(unit = ifelse(.data$unit == "/", NA, .data$unit)) From 33043b48cfa7221158e8b1ebd154fd8288045e5d Mon Sep 17 00:00:00 2001 From: Droomelot De Gendt Date: Tue, 7 Jul 2026 10:46:19 +0200 Subject: [PATCH 2/3] build: add git-blame-ignore-revs file to keep git blame clean and ignore specific style-commit --- .Rbuildignore | 2 ++ .git-blame-ignore-revs | 6 ++++++ 2 files changed, 8 insertions(+) create mode 100644 .git-blame-ignore-revs diff --git a/.Rbuildignore b/.Rbuildignore index 74168fb..264de78 100644 --- a/.Rbuildignore +++ b/.Rbuildignore @@ -9,3 +9,5 @@ ^appveyor\.yml$ ^\.zenodo\.json$ ^\.github$ +^\.positai$ +^\.claude$ diff --git a/.git-blame-ignore-revs b/.git-blame-ignore-revs new file mode 100644 index 0000000..ed3473f --- /dev/null +++ b/.git-blame-ignore-revs @@ -0,0 +1,6 @@ +# Run this command to always ignore the commits from this file with git blame +# git blame on Github will automatically take this file into account +# git config blame.ignoreRevsFile .git-blame-ignore-revs + +# Apply air formatter and RStudio Reflow Comment to R/get.R +59153b4c1ea47a4500f9bbff1261e3edf5a4a63d From 81e4de5856fb55e2b43a93966eff6d9db6a17104 Mon Sep 17 00:00:00 2001 From: Droomelot De Gendt Date: Tue, 14 Jul 2026 10:42:57 +0200 Subject: [PATCH 3/3] chore: add git-blame-ignore to buildignore --- .Rbuildignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.Rbuildignore b/.Rbuildignore index 264de78..504e7db 100644 --- a/.Rbuildignore +++ b/.Rbuildignore @@ -9,5 +9,6 @@ ^appveyor\.yml$ ^\.zenodo\.json$ ^\.github$ +^\.git-blame-ignore-revs ^\.positai$ ^\.claude$