From 1d6a51fe4dbfe5fabb69611cb7e7b9e1c77c7f97 Mon Sep 17 00:00:00 2001 From: Marco Colombo Date: Tue, 3 Sep 2024 09:20:21 +0200 Subject: [PATCH] Support vectors and single-column data frames in plot_KDE(). --- NEWS.Rmd | 5 ++++ R/plot_KDE.R | 51 ++++++++++++++++++++-------------- man/plot_KDE.Rd | 7 +++-- tests/testthat/test_plot_KDE.R | 6 ++++ 4 files changed, 46 insertions(+), 23 deletions(-) diff --git a/NEWS.Rmd b/NEWS.Rmd index c0386fe79..952277445 100644 --- a/NEWS.Rmd +++ b/NEWS.Rmd @@ -56,6 +56,11 @@ which would generate unexpected warnings (#163, @mcol). * The function now calculates the relative saturation (`n/N`) using the ration of the two integrates. The values is part of the output table. +### `plot_KDE()` +* It now officially supports numeric vectors and single-column data frames, +for which it assumes that the De error at each measurement is 10^-9 (#189, +fixed in #194, @mcol). + ### `plot_NRt()` * The function reports an helpful message rather than crashing when applied to an object of unexpected type or when there is a mismatch in time values diff --git a/R/plot_KDE.R b/R/plot_KDE.R index c2bd7e960..a843d4579 100644 --- a/R/plot_KDE.R +++ b/R/plot_KDE.R @@ -43,8 +43,11 @@ #' with the appropriate keyword using the argument `summary.method`. #' #' -#' @param data [data.frame] or [RLum.Results-class] object (**required**): -#' for `data.frame`: two columns: De (`values[,1]`) and De error (`values[,2]`). +#' @param data [data.frame], [vector] or [RLum.Results-class] object (**required**): +#' for `data.frame`: either two columns: De (`values[,1]`) and De error +#' (`values[,2]`), or one: De (`values[,1]`). If a numeric vector or a +#' single-column data frame is provided, De error is assumed to be 10^-9 +#' for all measurements and error bars are not drawn. #' For plotting multiple data sets, these must be provided as #' `list` (e.g. `list(dataset1, dataset2)`). #' @@ -222,12 +225,16 @@ plot_KDE <- function( data[[i]] <- get_RLum(data[[i]], "data")[,1:2] } - ##make sure we only take the first two columns - data[[i]] <- data[[i]][,1:2] - - ##account for very short datasets - if(length(data[[i]]) < 2) { - data[[i]] <- cbind(data[[i]], rep(NA, length(data[[i]]))) + ## if `data[[i]]` is a numeric vector or a single-column data frame, + ## append a second column with a small non-zero value (10^-9 for + ## consistency with what `calc_Statistics() does) + if (NCOL(data[[i]]) < 2) { + data[[i]] <- data.frame(data[[i]], 10^-9) + attr(data[[i]], "De.errors.available") <- FALSE + } else { + ## keep only the first two columns + data[[i]] <- data[[i]][, 1:2] + attr(data[[i]], "De.errors.available") <- TRUE } } @@ -280,13 +287,16 @@ plot_KDE <- function( ## optionally, count and exclude NA values and print result if(na.rm == TRUE) { for(i in 1:length(data)) { - n.NA <- sum(is.na(data[[i]][,1])) + na.idx <- which(is.na(data[[i]][, 1])) + n.NA <- length(na.idx) if(n.NA == 1) { message(paste("1 NA value excluded from data set", i, ".")) } else if(n.NA > 1) { message(paste(n.NA, "NA values excluded from data set", i, ".")) } - data[[i]] <- na.exclude(data[[i]]) + if (n.NA > 0) { + data[[i]] <- data[[i]][-na.idx, ] + } } } @@ -368,8 +378,6 @@ plot_KDE <- function( De.density.range[i,1:4] <- NA De.stats[i,4] <- NA } - - } ## Get global range of densities @@ -1210,15 +1218,16 @@ plot_KDE <- function( ## add De error bars for(i in 1:length(data)) { - arrows(data[[i]][,1] - data[[i]][,2], - 1:length(data[[i]][,1]), - data[[i]][,1] + data[[i]][,2], - 1:length(data[[i]][,1]), - code = 3, - angle = 90, - length = 0.05, - col = col.value.bar[i]) - + if (attr(data[[i]], "De.errors.available")) { + arrows(data[[i]][, 1] - data[[i]][, 2], + 1:length(data[[i]][,1]), + data[[i]][, 1] + data[[i]][, 2], + 1:length(data[[i]][, 1]), + code = 3, + angle = 90, + length = 0.05, + col = col.value.bar[i]) + } ## add De measurements points(data[[i]][,1], 1:De.stats[i,1], col = col.value.dot[i], diff --git a/man/plot_KDE.Rd b/man/plot_KDE.Rd index b5ff05803..9a01c1696 100644 --- a/man/plot_KDE.Rd +++ b/man/plot_KDE.Rd @@ -20,8 +20,11 @@ plot_KDE( ) } \arguments{ -\item{data}{\link{data.frame} or \linkS4class{RLum.Results} object (\strong{required}): -for \code{data.frame}: two columns: De (\code{values[,1]}) and De error (\code{values[,2]}). +\item{data}{\link{data.frame}, \link{vector} or \linkS4class{RLum.Results} object (\strong{required}): +for \code{data.frame}: either two columns: De (\code{values[,1]}) and De error +(\code{values[,2]}), or one: De (\code{values[,1]}). If a numeric vector or a +single-column data frame is provided, De error is assumed to be 10^-9 +for all measurements and error bars are not drawn. For plotting multiple data sets, these must be provided as \code{list} (e.g. \code{list(dataset1, dataset2)}).} diff --git a/tests/testthat/test_plot_KDE.R b/tests/testthat/test_plot_KDE.R index 887c9b831..9d3cd8348 100644 --- a/tests/testthat/test_plot_KDE.R +++ b/tests/testthat/test_plot_KDE.R @@ -50,6 +50,12 @@ test_that("check functionality", { expect_silent(plot_KDE(data = df, summary.pos = "bottom")) expect_silent(plot_KDE(data = df, summary.pos = "bottomright")) + ## numeric vector + expect_silent(plot_KDE(df[, 1])) + + ## single-column data.frame + expect_silent(plot_KDE(df[, 1, drop = FALSE])) + ## RLum.Results object expect_silent(plot_KDE(calc_CommonDose(df, plot = FALSE, verbose = FALSE)))