From 93b3b43556a25a3a841d869b2ac9e1aafb4b9a9b Mon Sep 17 00:00:00 2001 From: Damiano Oldoni Date: Mon, 27 Mar 2023 10:48:53 +0200 Subject: [PATCH 1/9] Replace data with df See https://github.com/trias-project/trias/issues/64#issuecomment-1482818789 --- R/indicator_native_range_year.R | 12 ++++++------ man/indicator_native_range_year.Rd | 4 ++-- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/R/indicator_native_range_year.R b/R/indicator_native_range_year.R index 7f24ae9a..046a7c92 100644 --- a/R/indicator_native_range_year.R +++ b/R/indicator_native_range_year.R @@ -4,7 +4,7 @@ #' Based on #' [countYearProvince](https://github.com/inbo/reporting-rshiny-grofwildjacht/blob/exoten/reporting-grofwild/R/countYearProvince.R) #' plot from reporting - rshiny - grofwildjacht -#' @param data input data.frame. +#' @param df input data.frame. #' @param years (numeric) vector years we are interested to. If \code{NULL} #' (default) all years from minimum and maximum of years of first observation #' are taken into account. @@ -29,7 +29,7 @@ #' @export #' @importFrom dplyr %>% .data -indicator_native_range_year <- function(data, years = NULL, +indicator_native_range_year <- function(df, years = NULL, type = c("native_continent", "native_range"), x_lab = "year", y_lab = "alien species", @@ -38,15 +38,15 @@ indicator_native_range_year <- function(data, years = NULL, type <- match.arg(type) # Rename to default column name - data <- - data %>% + df <- + df %>% dplyr::rename_at(dplyr::vars(first_observed), ~"first_observed") if (is.null(years)) { - years <- sort(unique(data$first_observed)) + years <- sort(unique(df$first_observed)) } - plotData <- data + plotData <- df plotData$location <- switch(type, native_range = plotData$native_range, diff --git a/man/indicator_native_range_year.Rd b/man/indicator_native_range_year.Rd index d2c78c60..ef1cede1 100644 --- a/man/indicator_native_range_year.Rd +++ b/man/indicator_native_range_year.Rd @@ -6,7 +6,7 @@ and year of introduction} \usage{ indicator_native_range_year( - data, + df, years = NULL, type = c("native_continent", "native_range"), x_lab = "year", @@ -16,7 +16,7 @@ indicator_native_range_year( ) } \arguments{ -\item{data}{input data.frame.} +\item{df}{input data.frame.} \item{years}{(numeric) vector years we are interested to. If \code{NULL} (default) all years from minimum and maximum of years of first observation From 37d33a0bb42060f015226822ed65f46f03b75800 Mon Sep 17 00:00:00 2001 From: Damiano Oldoni Date: Mon, 27 Mar 2023 10:49:02 +0200 Subject: [PATCH 2/9] Bump version --- DESCRIPTION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/DESCRIPTION b/DESCRIPTION index 5cec6fe7..001f9534 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -1,7 +1,7 @@ Package: trias Title: Process Data for the Project Tracking Invasive Alien Species (TrIAS) -Version: 2.0.5 +Version: 2.0.6 Authors@R: c( person("Damiano", "Oldoni", email = "damiano.oldoni@inbo.be", role = c("aut", "cre"), comment = c(ORCID = "0000-0003-3445-7562")), From 51d1239dc4d9a70c494b85c263e6f0a8d3bc4e36 Mon Sep 17 00:00:00 2001 From: Damiano Oldoni Date: Mon, 27 Mar 2023 11:24:29 +0200 Subject: [PATCH 3/9] Add example to function documentation --- R/indicator_native_range_year.R | 26 +++++++++++++++++++------- 1 file changed, 19 insertions(+), 7 deletions(-) diff --git a/R/indicator_native_range_year.R b/R/indicator_native_range_year.R index 046a7c92..b3c7a8de 100644 --- a/R/indicator_native_range_year.R +++ b/R/indicator_native_range_year.R @@ -28,7 +28,25 @@ #' introduced from the native range for a given year. (n/total)*100} } } } #' @export #' @importFrom dplyr %>% .data - +#' @examples +#' \dontrun{ +#' library(readr) +#' datafile <- paste0( +#' "https://raw.githubusercontent.com/trias-project/indicators/master/data/", +#' "interim/data_input_checklist_indicators.tsv" +#' ) +#' data <- read_tsv(datafile, +#' na = "", +#' col_types = cols( +#' .default = col_character(), +#' key = col_double(), +#' nubKey = col_double(), +#' speciesKey = col_double(), +#' first_observed = col_double(), +#' last_observed = col_double() +#' ) +#' ) +#' indicator_native_range_year(data, years = c(2010,2013)) indicator_native_range_year <- function(df, years = NULL, type = c("native_continent", "native_range"), x_lab = "year", @@ -56,17 +74,11 @@ indicator_native_range_year <- function(df, years = NULL, # Select data plotData <- plotData[plotData$first_observed %in% years, c("first_observed", "location")] plotData <- plotData[!is.na(plotData$first_observed) & !is.na(plotData$location), ] - # Exclude unused provinces plotData$location <- as.factor(plotData$location) plotData$location <- droplevels(plotData$location) # Summarize data per native_range and year - plotData$first_observed <- with(plotData, factor(first_observed, - levels = - min(years):max(years) - )) - summaryData <- reshape2::melt(table(plotData), id.vars = "first_observed") summaryData <- summaryData %>% dplyr::group_by(.data$first_observed) %>% From 03893864404d0d317cb602b4af6ec5e0e057f987 Mon Sep 17 00:00:00 2001 From: Damiano Oldoni Date: Mon, 27 Mar 2023 11:24:56 +0200 Subject: [PATCH 4/9] Fix #105 --- R/indicator_native_range_year.R | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/R/indicator_native_range_year.R b/R/indicator_native_range_year.R index b3c7a8de..25bb1df6 100644 --- a/R/indicator_native_range_year.R +++ b/R/indicator_native_range_year.R @@ -74,6 +74,10 @@ indicator_native_range_year <- function(df, years = NULL, # Select data plotData <- plotData[plotData$first_observed %in% years, c("first_observed", "location")] plotData <- plotData[!is.na(plotData$first_observed) & !is.na(plotData$location), ] + + # Exclude unused provinces + plotData$first_observed <- as.factor(plotData$first_observed) + # Exclude unused provinces plotData$location <- as.factor(plotData$location) plotData$location <- droplevels(plotData$location) From 703e73503238d04efe3a865680b3be51628a74e2 Mon Sep 17 00:00:00 2001 From: Damiano Oldoni Date: Mon, 27 Mar 2023 11:26:26 +0200 Subject: [PATCH 5/9] Import package in testthat for tests --- tests/testthat.R | 1 + tests/testthat/test-gbif_verify_keys.R | 2 -- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/tests/testthat.R b/tests/testthat.R index 608d88c6..d933c8b9 100644 --- a/tests/testthat.R +++ b/tests/testthat.R @@ -1,4 +1,5 @@ library(testthat) +library(purrr) library(trias) test_check("trias") diff --git a/tests/testthat/test-gbif_verify_keys.R b/tests/testthat/test-gbif_verify_keys.R index fab2440b..414abafc 100644 --- a/tests/testthat/test-gbif_verify_keys.R +++ b/tests/testthat/test-gbif_verify_keys.R @@ -1,5 +1,3 @@ -#' @importFrom purrr map_chr -#' context("test_gbif_verify_keys") test_that("test several input types", { From 42f6b4d8009255f3d6c4d39683b0371ad0cc79d7 Mon Sep 17 00:00:00 2001 From: Damiano Oldoni Date: Wed, 29 Mar 2023 16:09:10 +0200 Subject: [PATCH 6/9] Improve documentation and args --- R/indicator_native_range_year.R | 41 ++++++++++++++++++++++-------- man/indicator_native_range_year.Rd | 31 +++++++++++++++++++--- 2 files changed, 58 insertions(+), 14 deletions(-) diff --git a/R/indicator_native_range_year.R b/R/indicator_native_range_year.R index 25bb1df6..5d612f76 100644 --- a/R/indicator_native_range_year.R +++ b/R/indicator_native_range_year.R @@ -9,12 +9,16 @@ #' (default) all years from minimum and maximum of years of first observation #' are taken into account. #' @param type character, native_range level of interest should be one of -#' \code{c("native_continent", "native_range")}. +#' `c("native_range", "native_continent")`. Default: `"native_range"`. A +#' column called as the selected `type` must be present in `df`. #' @param x_lab character string, label of the x-axis. Default: "year". #' @param y_lab character string, label of the y-axis. Default: "number of alien #' species". -#' @param relative (logical) if TRUE, each bar is standardised before stacking -#' @param first_observed (character) Name of the column in \code{data} containing temporal information about introduction of the alien species. Expressed as years. +#' @param relative (logical) if TRUE (default), each bar is standardised before +#' stacking. +#' @param first_observed (character) Name of the column in `data` +#' containing temporal information about introduction of the alien species. +#' Expressed as years. #' @return list with: \itemize{ \item{'static_plot': }{ggplot object, for a #' given species the observed number per year and per native range is plotted #' in a stacked bar chart} \item{'interactive_plot': }{plotly object, for a @@ -46,15 +50,30 @@ #' last_observed = col_double() #' ) #' ) -#' indicator_native_range_year(data, years = c(2010,2013)) -indicator_native_range_year <- function(df, years = NULL, - type = c("native_continent", "native_range"), - x_lab = "year", - y_lab = "alien species", - relative = FALSE, - first_observed = "first_observed") { +#' indicator_native_range_year(data, "native_continent", years = c(2010,2013)) +#' } +indicator_native_range_year <- function( + df, + years = NULL, + type = c("native_range", "native_continent"), + x_lab = "year", + y_lab = "alien species", + relative = FALSE, + first_observed = "first_observed") { + # initial input checks + assertthat::assert_that(is.data.frame(df)) + if (!is.null(years)) { + assertthat::assert_that(all(is.numeric(years)), + msg = "Argument years has to be a number." + ) + assertthat::assert_that( + all(years < as.integer(format(Sys.Date(), "%Y"))), + msg = sprintf( + "All values in years has to be less than %s.", format(Sys.Date(), "%Y") + ) + ) + } type <- match.arg(type) - # Rename to default column name df <- df %>% diff --git a/man/indicator_native_range_year.Rd b/man/indicator_native_range_year.Rd index ef1cede1..24b6c349 100644 --- a/man/indicator_native_range_year.Rd +++ b/man/indicator_native_range_year.Rd @@ -23,16 +23,20 @@ indicator_native_range_year( are taken into account.} \item{type}{character, native_range level of interest should be one of -\code{c("native_continent", "native_range")}.} +\code{c("native_continent", "native_range")}. Default: \code{"native_continent"}. A +column called as the selected \code{type} must be present in \code{df}.} \item{x_lab}{character string, label of the x-axis. Default: "year".} \item{y_lab}{character string, label of the y-axis. Default: "number of alien species".} -\item{relative}{(logical) if TRUE, each bar is standardised before stacking} +\item{relative}{(logical) if TRUE (default), each bar is standardised before +stacking.} -\item{first_observed}{(character) Name of the column in \code{data} containing temporal information about introduction of the alien species. Expressed as years.} +\item{first_observed}{(character) Name of the column in \code{data} +containing temporal information about introduction of the alien species. +Expressed as years.} } \value{ list with: \itemize{ \item{'static_plot': }{ggplot object, for a @@ -52,3 +56,24 @@ Based on \href{https://github.com/inbo/reporting-rshiny-grofwildjacht/blob/exoten/reporting-grofwild/R/countYearProvince.R}{countYearProvince} plot from reporting - rshiny - grofwildjacht } +\examples{ +\dontrun{ +library(readr) +datafile <- paste0( + "https://raw.githubusercontent.com/trias-project/indicators/master/data/", + "interim/data_input_checklist_indicators.tsv" +) +data <- read_tsv(datafile, + na = "", + col_types = cols( + .default = col_character(), + key = col_double(), + nubKey = col_double(), + speciesKey = col_double(), + first_observed = col_double(), + last_observed = col_double() + ) +) +indicator_native_range_year(data, "native_continent", years = c(2010,2013)) +} +} From 5c14711dfebb138dedd4053243e97e0606121da9 Mon Sep 17 00:00:00 2001 From: Damiano Oldoni Date: Wed, 29 Mar 2023 16:09:25 +0200 Subject: [PATCH 7/9] Improve assertions --- R/indicator_native_range_year.R | 27 ++++++++++++++++++++++++--- 1 file changed, 24 insertions(+), 3 deletions(-) diff --git a/R/indicator_native_range_year.R b/R/indicator_native_range_year.R index 5d612f76..dfc76699 100644 --- a/R/indicator_native_range_year.R +++ b/R/indicator_native_range_year.R @@ -74,6 +74,29 @@ indicator_native_range_year <- function( ) } type <- match.arg(type) + assertthat::assert_that(type %in% names(df), + msg = sprintf("Column %s not present in df.", type) + ) + if (!is.null(x_lab)) { + assertthat::assert_that(is.character(x_lab), + msg = "Argument x_lab has to be a character or NULL." + ) + } + if (!is.null(y_lab)) { + assertthat::assert_that(is.character(y_lab), + msg = "Argument y_lab has to be a character or NULL." + ) + + } + assertthat::assert_that(is.logical(relative), + msg = "Argument relative has to be a logical." + ) + assertthat::assert_that(is.character(first_observed), + msg = "Argument first_observed has to be a character." + ) + assertable::assert_colnames(df, first_observed, only_colnames = FALSE) + + # Rename to default column name df <- df %>% @@ -94,10 +117,8 @@ indicator_native_range_year <- function( plotData <- plotData[plotData$first_observed %in% years, c("first_observed", "location")] plotData <- plotData[!is.na(plotData$first_observed) & !is.na(plotData$location), ] - # Exclude unused provinces + # Set location and first_observed to factors plotData$first_observed <- as.factor(plotData$first_observed) - - # Exclude unused provinces plotData$location <- as.factor(plotData$location) plotData$location <- droplevels(plotData$location) From 67fc4cbd1df09dae6a1f5a1136da04f0c6d4473b Mon Sep 17 00:00:00 2001 From: Damiano Oldoni Date: Wed, 29 Mar 2023 16:09:32 +0200 Subject: [PATCH 8/9] Add unit-tests --- .../test-indicator_native_range_year.R | 146 ++++++++++++++++++ 1 file changed, 146 insertions(+) create mode 100644 tests/testthat/test-indicator_native_range_year.R diff --git a/tests/testthat/test-indicator_native_range_year.R b/tests/testthat/test-indicator_native_range_year.R new file mode 100644 index 00000000..f3109566 --- /dev/null +++ b/tests/testthat/test-indicator_native_range_year.R @@ -0,0 +1,146 @@ +context("test_indicator_native_range_year") + +# test df +input_test_df <- read.delim( + test_path("data_test_input_graphs_indicators/test_visualization_df.tsv"), + sep = "\t" +) + +nrow_no_first_obs <- + nrow(input_test_df[is.na(input_test_df$first_observed), ]) + +cleaned_input_test_df <- input_test_df[!is.na(input_test_df$first_observed), ] + +test_that("Arg: df", { + expect_error( + indicator_native_range_year(3), + "df is not a data frame" + ) +}) + + +test_that("Arg: type", { + expect_error( + indicator_native_range_year(cleaned_input_test_df, + type = 2, + years = 2001), + "'arg' must be NULL or a character vector" + ) + expect_error( + indicator_native_range_year(cleaned_input_test_df, + type = "aaa", + years = 2001), + "'arg' should be one of “native_range”, “native_continent”" + ) + a <- cleaned_input_test_df + colnames(a)[colnames(a) == "native_range"] <- "l" + expect_error( + indicator_native_range_year(a, + type = "native_range", + years = 2001), + "Column native_range not present in df." + ) +}) + + +test_that("Arg: years", { + expect_error( + indicator_native_range_year(cleaned_input_test_df, + years = "2000" + ), + "Argument years has to be a number." + ) + expect_error( + indicator_native_range_year(cleaned_input_test_df, + years = c(2000,3000) + ), + sprintf("All values in years has to be less than %s.", format(Sys.Date(), "%Y")) + ) +}) + +test_that("Arg: first_observed", { + expect_error( + indicator_native_range_year(input_test_df, + years = 2010, + first_observed = 3), + "Argument first_observed has to be a character." + ) + expect_error( + indicator_native_range_year(input_test_df, + year = 2010, + first_observed = "bad_colname" + ) + ) +}) + +test_that("Param: labels", { + expect_error( + indicator_native_range_year(input_test_df, x_lab = input_test_df), + "Argument x_lab has to be a character or NULL." + ) + expect_error( + indicator_native_range_year(input_test_df, y_lab = 4), + "Argument y_lab has to be a character or NULL." + ) +}) + +test_that("Test output type, class, slots and columns", { + plot_output <- + indicator_native_range_year(cleaned_input_test_df, + years = c(2000,2005) + ) + plot_output_rel <- + indicator_native_range_year(cleaned_input_test_df, + years = c(2000,2005), + relative = TRUE + ) + # output is a list + expect_type(plot_output, type = "list") + expect_type(plot_output_rel, type = "list") + + # output has the right three slots + slots <- c("static_plot", "interactive_plot", "data") + expect_equal(names(plot_output), slots) + expect_equal(names(plot_output_rel), slots) + + # static plot slot is a list with gg as class + expect_type(plot_output$static_plot, type = "list") + expect_type(plot_output_rel$static_plot, type = "list") + expect_s3_class(plot_output$static_plot, class = c("gg", "ggplot")) + expect_s3_class(plot_output_rel$static_plot, class = c("gg", "ggplot")) + + # interactive plot slot is a list with plotly and htmlwidget as class + expect_type(plot_output$interactive_plot, type = "list") + expect_type(plot_output_rel$interactive_plot, type = "list") + expect_s3_class(plot_output$interactive_plot, class = c("plotly", "htmlwidget")) + expect_s3_class(plot_output_rel$interactive_plot, class = c("plotly", "htmlwidget")) + + # data is a data.frame (tibble) + expect_type(plot_output$data, type = "list") + expect_s3_class(plot_output$data, class = c("data.frame", "tbl_df")) + expect_type(plot_output_rel$data, type = "list") + expect_s3_class(plot_output_rel$data, class = c("data.frame", "tbl_df")) + + # data contains only columns year, native_range, n, total and perc in this + # order + expect_equal( + names(plot_output$data), + c("year", "native_range", "n", "total", "perc") + ) + expect_equal( + names(plot_output_rel$data), + c("year", "native_range", "n", "total", "perc") + ) + + # columns year and native_range of data slot are factors + expect_true(is.factor(plot_output$data$year)) + expect_true(is.factor(plot_output$data$native_range)) + # columns n and total of data slot are integers + expect_true(is.integer(plot_output$data$n)) + expect_true(is.integer(plot_output$data$total)) + # column perc of data slot is double + expect_true(is.double(plot_output$data$perc)) + + # data slot is not affected by value of related arg + expect_identical(plot_output$data, plot_output_rel$data) +}) From 7221ea2235f8295174700deb339a93f35de3089e Mon Sep 17 00:00:00 2001 From: Damiano Oldoni Date: Wed, 29 Mar 2023 16:36:03 +0200 Subject: [PATCH 9/9] Remove test around match.arg MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Problematic in R CMD check as “ “ are converted to \" \" --- man/indicator_native_range_year.Rd | 4 ++-- tests/testthat/test-indicator_native_range_year.R | 6 ------ 2 files changed, 2 insertions(+), 8 deletions(-) diff --git a/man/indicator_native_range_year.Rd b/man/indicator_native_range_year.Rd index 24b6c349..d82fbd0a 100644 --- a/man/indicator_native_range_year.Rd +++ b/man/indicator_native_range_year.Rd @@ -8,7 +8,7 @@ and year of introduction} indicator_native_range_year( df, years = NULL, - type = c("native_continent", "native_range"), + type = c("native_range", "native_continent"), x_lab = "year", y_lab = "alien species", relative = FALSE, @@ -23,7 +23,7 @@ indicator_native_range_year( are taken into account.} \item{type}{character, native_range level of interest should be one of -\code{c("native_continent", "native_range")}. Default: \code{"native_continent"}. A +\code{c("native_range", "native_continent")}. Default: \code{"native_range"}. A column called as the selected \code{type} must be present in \code{df}.} \item{x_lab}{character string, label of the x-axis. Default: "year".} diff --git a/tests/testthat/test-indicator_native_range_year.R b/tests/testthat/test-indicator_native_range_year.R index f3109566..5374163c 100644 --- a/tests/testthat/test-indicator_native_range_year.R +++ b/tests/testthat/test-indicator_native_range_year.R @@ -26,12 +26,6 @@ test_that("Arg: type", { years = 2001), "'arg' must be NULL or a character vector" ) - expect_error( - indicator_native_range_year(cleaned_input_test_df, - type = "aaa", - years = 2001), - "'arg' should be one of “native_range”, “native_continent”" - ) a <- cleaned_input_test_df colnames(a)[colnames(a) == "native_range"] <- "l" expect_error(