From 2b2d57e1b4f8661355865929ad987c012c13e235 Mon Sep 17 00:00:00 2001 From: Andreas Busjahn Date: Tue, 28 Nov 2023 10:33:41 +0100 Subject: [PATCH] label_outliers uses rownames/numbers if no labelvar detect_outliers returns now a list with values and positions --- R/plots.R | 46 +++++++++++++++++++++++++----------------- man/detect_outliers.Rd | 5 ++++- man/label_outliers.Rd | 4 ++-- 3 files changed, 34 insertions(+), 21 deletions(-) diff --git a/R/plots.R b/R/plots.R index 0fbbc8d..880488e 100644 --- a/R/plots.R +++ b/R/plots.R @@ -227,7 +227,7 @@ ggcormat <- function(cor_mat, p_mat = NULL, #' @param plotbase ggplot object to add labels to. # ' @param xvar x variable for grouping. # ' @param yvar y variable with possible outliers. -#' @param labelvar variable to use as label. +#' @param labelvar variable to use as label. If NULL, rownames or rownumbers are used. #' @param coef coefficient for boxplot.stats, defaults to 1.5. #' @param nudge_x nudge in x direction, defaults to 0. #' @param nudge_y nudge in y direction, defaults to 0. @@ -241,40 +241,46 @@ ggcormat <- function(cor_mat, p_mat = NULL, # ' @examples # todo: group by facet variables #' @export -label_outliers <- function(plotbase, labelvar, #xvar, #yvar, +label_outliers <- function(plotbase, labelvar=NULL, #xvar, #yvar, coef=1.5, nudge_x=0, nudge_y=0, color="darkred", size=3, hjust=0, face="bold") { if(!requireNamespace("ggrepel", quietly = TRUE)) { stop("ggrepel package is required") } + plotdata <- plotbase$data + if(is.null(labelvar)) { + labelvar <- "Position" + plotdata <- mutate(plotdata, Position = row.names(plotdata)) + } + plotlist <- ggplot_build(plotbase) xvar <- plotbase$mapping[["x"]] |> as_label() - # plotlist[["plot"]][["layers"]][[1]][["computed_mapping"]][1] |> - # as.character() |> - # str_remove("~") + # plotlist[["plot"]][["layers"]][[1]][["computed_mapping"]][1] |> + # as.character() |> + # str_remove("~") yvar <- plotbase$mapping[["y"]] |> as_label() - #plotbase$layers[[1]]$computed_mapping[2] |> - # plotlist[["plot"]][["layers"]][[1]][["computed_mapping"]][2] |> - # as.character() |> - # str_replace_all( - # c('^.+\\"(.+)\\".*'="\\1", - # "~"="")) + #plotbase$layers[[1]]$computed_mapping[2] |> + # plotlist[["plot"]][["layers"]][[1]][["computed_mapping"]][2] |> + # as.character() |> + # str_replace_all( + # c('^.+\\"(.+)\\".*'="\\1", + # "~"="")) # groupvars <- xvar # if(!is.null(plotlist$layout$facet$params$row)){ - facet_rows <- names(plotlist$layout$facet$params$row) - # groupvars <- c(groupvars,facet_rows) + facet_rows <- names(plotlist$layout$facet$params$row) + # groupvars <- c(groupvars,facet_rows) # } # if(!is.null(plotlist$layout$facet$params$col)){ - facet_cols <- names(plotlist$layout$facet$params$col) + facet_cols <- names(plotlist$layout$facet$params$col) facet_wraps <- names(plotlist$layout$facet$params$facets) groupvars <- c(xvar,facet_rows,facet_cols,facet_wraps) outpositions <- plotbase$data |> group_by(across(all_of(groupvars))) |> reframe(across(all_of(yvar), - ~detect_outliers(.x, coef=coef))) |> - left_join(plotbase$data) + ~detect_outliers(.x, coef=coef)$outliers)) |> + left_join(plotdata) plotbase + ggrepel::geom_text_repel(data=outpositions, aes(label=!!sym(labelvar)), @@ -297,14 +303,18 @@ label_outliers <- function(plotbase, labelvar, #xvar, #yvar, #' @param x numeric vector. #' @param coef coefficient for boxplot.stats, defaults to 1.5. #' -#' @return A numeric vector with outliers. +#' @return A list with elements positions and outliers as numeric vectors. #' +#' @examples +#' detect_outliers(rnorm(100)) #' @export detect_outliers <- function(x, coef=1.5) { qnt <- quantile(x, probs=c(.25, .75), na.rm = TRUE) iqr <- diff(qnt) upper <- qnt[2] + coef * iqr lower <- qnt[1] - coef * iqr - out <- x[x > upper | x < lower] + o_pos <- which(x > upper | x < lower) + out <- list("positions"=o_pos, + "outliers"=x[o_pos]) return(out) } diff --git a/man/detect_outliers.Rd b/man/detect_outliers.Rd index d22370e..e421d7d 100644 --- a/man/detect_outliers.Rd +++ b/man/detect_outliers.Rd @@ -12,10 +12,13 @@ detect_outliers(x, coef = 1.5) \item{coef}{coefficient for boxplot.stats, defaults to 1.5.} } \value{ -A numeric vector with outliers. +A list with elements positions and outliers as numeric vectors. } \description{ \ifelse{html}{\href{https://lifecycle.r-lib.org/articles/stages.html#experimental}{\figure{lifecycle-experimental.svg}{options: alt='[Experimental]'}}}{\strong{[Experimental]}} \code{detect_outliers} computes IQR and finds outliers. It gives the same results as \code{geom_boxplot} and thus differs slightly from \code{boxplot.stats}. } +\examples{ +detect_outliers(rnorm(100)) +} diff --git a/man/label_outliers.Rd b/man/label_outliers.Rd index 62b36ae..46ea2b3 100644 --- a/man/label_outliers.Rd +++ b/man/label_outliers.Rd @@ -6,7 +6,7 @@ \usage{ label_outliers( plotbase, - labelvar, + labelvar = NULL, coef = 1.5, nudge_x = 0, nudge_y = 0, @@ -19,7 +19,7 @@ label_outliers( \arguments{ \item{plotbase}{ggplot object to add labels to.} -\item{labelvar}{variable to use as label.} +\item{labelvar}{variable to use as label. If NULL, rownames or rownumbers are used.} \item{coef}{coefficient for boxplot.stats, defaults to 1.5.}