#' Run any function with a maximum missing fraction of X and 0s possibly
#' counting as missing. The maximum fraction missing comes from
#' `PKNCA.options("max.missing")`.
#'
#' Note that all missing values are removed prior to calling the function.
#'
#' @param FUN function to run. The function is called as `FUN(x, ...)` with
#' missing values removed.
#' @param zero.missing Are zeros counted as missing? If `TRUE` then include
#' them in the missing count.
#' @param max.missing The maximum fraction of the data allowed to be missing (a
#' number between 0 and 1, inclusive).
#' @returns A version of FUN that can be called with parameters that are checked
#' for missingness (and zeros) with missing (and zeros) removed before the
#' call. If `max.missing` is exceeded, then NA is returned.
#' @examples
#' my_mean <- pk.business(FUN=mean)
#' mean(c(1:3, NA))
#' # Less than half missing results in the summary statistic of the available
#' # values.
#' my_mean(c(1:3, NA))
#' # More than half missing results in a missing value
#' my_mean(c(1:3, rep(NA, 4)))
#' @export
pk.business <- function(FUN,
zero.missing=FALSE,
max.missing)
function(x, ...) {
# Allow max.missing to be specified at either function initiation or for it
# to use PKNCA.Options("max.missing")
max.missing <- PKNCA.options("max.missing")
mask.missing <- is.na(x) | (zero.missing & (x %in% 0))
if (sum(mask.missing)/length(x) > max.missing)
return(NA)
ret <- FUN(x[!mask.missing], ...)
attr(ret, "n") <- sum(!mask.missing)
ret
}
#' Compute the geometric mean, sd, and CV
#'
#' @param x A vector to compute the geometric mean of
#' @param na.rm Should missing values be removed?
#' @return The scalar value of the geometric mean, geometric standard deviation,
#' or geometric coefficient of variation.
#' @references Kirkwood T. B.L. Geometric means and measures of dispersion.
#' Biometrics 1979; 35: 908-909
#' @examples
#' geomean(1:3)
#' @export
geomean <- function(x, na.rm=FALSE) {
if (na.rm)
x <- stats::na.omit(x)
if (any(is.na(x))) {
as.numeric(NA)
} else if (any(x == 0)) {
0
} else if (any(x < 0)) {
# Protect from overflows by using the logarithm
prod(sign(x))*exp(sum(log(abs(x)))/length(x))
} else {
exp(sum(log(x))/length(x))
}
}
#' @describeIn geomean
#' Compute the geometric standard deviation, `exp(sd(log(x)))`.
#' @examples
#' geosd(1:3)
#' @export
geosd <- function(x, na.rm=FALSE) {
exp(stats::sd(log(x), na.rm=na.rm))
}
#' @describeIn geomean
#' Compute the geometric coefficient of variation,
#' `sqrt(exp(sd(log(x))^2)-1)*100`.
#' @examples
#' geocv(1:3)
#' @export
geocv <- function(x, na.rm=FALSE) {
sqrt(exp(stats::sd(log(x), na.rm=na.rm)^2)-1)*100
}
#' Generate functions to do the named function (e.g. mean) applying
#' the business rules.
#'
#' @param x vector to be passed to the various functions
#' @param ... Additional arguments to be passed to the underlying function.
#' @return The value of the various functions or NA if too many values are
#' missing
#' @seealso [pk.business()]
#' @export
business.mean <- pk.business(mean, max.missing=~PKNCA::PKNCA.Options("max.missing"))
#' @describeIn business.mean
#' Compute the standard deviation with business rules.
#' @export
business.sd <- pk.business(stats::sd, max.missing=~PKNCA::PKNCA.Options("max.missing"))
#' @describeIn business.mean
#' Compute the coefficient of variation with business rules.
#' @export
business.cv <-
pk.business(
function(x, ...) {
100*stats::sd(x, ...)/mean(x, ...)
},
max.missing=~PKNCA::PKNCA.Options("max.missing")
)
#' @describeIn business.mean
#' Compute the geometric mean with business rules.
#' @export
business.geomean <-
pk.business(
geomean, zero.missing=TRUE,
max.missing=~PKNCA::PKNCA.Options("max.missing")
)
#' @describeIn business.mean
#' Compute the geometric coefficient of variation with business rules.
#' @export
business.geocv <-
pk.business(
geocv, zero.missing=TRUE,
max.missing=~PKNCA::PKNCA.Options("max.missing")
)
#' @describeIn business.mean
#' Compute the minimum with business rules.
#' @export
business.min <-
pk.business(min, max.missing=~PKNCA::PKNCA.Options("max.missing"))
#' @describeIn business.mean
#' Compute the maximum with business rules.
#' @export
business.max <-
pk.business(max, max.missing=~PKNCA::PKNCA.Options("max.missing"))
#' @describeIn business.mean
#' Compute the median with business rules.
#' @export
business.median <-
pk.business(stats::median, max.missing=~PKNCA::PKNCA.Options("max.missing"))
#' @describeIn business.mean
#' Compute the range with business rules.
#' @export
business.range <-
pk.business(range, max.missing=~PKNCA::PKNCA.Options("max.missing"))
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.