R/init_freq_num.R

Defines functions comp_freq_col comp_freq_type comp_freq init_freq

Documented in comp_freq

## init_freq_num.R | riskyr
## 2021 03 25
## Compute current key frequencies (freq) based on num
## (using only 4 necessary parameters of num):
## -----------------------------------------------

## (1) Initialize key frequencies as a list (of NA values) freq: ---------
##     Currently 11 key frequencies (4 essential ones):

## init_freq Definition: ----

init_freq <- function() {

  ## (0) Initialize freq as a list:
  freq <- list(

    ## (1) Population size:
    "N" = NA, # Number of cases overall

    ## (2) Splits into 2 subgroups:
    ## (a) Number of true cases by condition
    ##     (= columns of confusion matrix):
    "cond_true"  = NA, # N of cond TRUE
    "cond_false" = NA, # N of cond FALSE

    ## (b) Number of decisions
    ##     (= rows of confusion matrix):
    "dec_pos" = NA, # N of dec POS [was: dec_true]
    "dec_neg" = NA, # N of dec NEG [was: dec_false]

    ## (c) Correspondence of decision to condition
    ##     (= diagonals of confusion matrix):
    "dec_cor" = NA, # N of correct decisions
    "dec_err" = NA, # N of erroneous decisions

    ## (3) Splits into 4 subgroups
    ##     (= 4 cells or SDT combinations of confusion matrix):
    "hi" = NA, # true positive
    "mi" = NA, # false negative
    "fa" = NA, # false positive
    "cr" = NA  # true negative
  )

  ## Return 11 key freq (as list):
  return(freq)

}

## Check:
# init_freq()          # initializes empty freq
# length(init_freq())  # 11 key frequencies


## (2) Compute key frequencies from 3 essential probabilities: --------

## comp_freq: Documentation ------

#' Compute frequencies from (3 essential) probabilities.
#'
#' \code{comp_freq} computes frequencies (typically
#' as rounded integers) given 3 basic probabilities --
#' \code{\link{prev}}, \code{\link{sens}}, and \code{\link{spec}} --
#' for a population of \code{\link{N}} individuals.
#' It returns a list of 11 key frequencies \code{\link{freq}}
#' as its output.
#'
#' In addition to \code{\link{prev}}, both
#' \code{\link{sens}} and \code{\link{spec}} are necessary arguments.
#' If only their complements \code{\link{mirt}} or \code{\link{fart}}
#' are known, use the wrapper function \code{\link{comp_freq_prob}}
#' which also accepts \code{\link{mirt}} and \code{\link{fart}} as inputs
#' (but requires that the entire set of provided probabilities is
#' sufficient and consistent).
#' Alternatively, use \code{\link{comp_complement}},
#' \code{\link{comp_comp_pair}}, or \code{\link{comp_complete_prob_set}}
#' to obtain the 3 essential probabilities.
#'
#' \code{comp_freq} is the frequency counterpart to the
#' probability function \code{\link{comp_prob}}.
#'
#' By default, \code{comp_freq} and its wrapper function
#' \code{\link{comp_freq_prob}}
#' round frequencies to nearest integers to avoid decimal values in
#' \code{\link{freq}} (i.e., \code{round = TRUE} by default).
#' When frequencies are rounded, probabilities computed from
#' \code{\link{freq}} may differ from exact probabilities.
#' Using the option \code{round = FALSE} turns off rounding.
#'
#' Key relationships between probabilities and frequencies:
#'
#' \itemize{
#'
#' \item Three perspectives on a population:
#'
#' A population of \code{\link{N}} individuals can be split into 2 subsets of frequencies
#' in 3 different ways:
#'
#'    \enumerate{
#'
#'    \item by condition:
#'
#'    \code{\link{N} = \link{cond_true} + \link{cond_false}}
#'
#'    The frequency \code{\link{cond_true}} depends on the prevalence \code{\link{prev}}
#'    and
#'    the frequency \code{\link{cond_false}} depends on the prevalence's complement \code{1 - \link{prev}}.
#'
#'    \item by decision:
#'
#'    \code{\link{N} = \link{dec_pos} + \link{dec_neg}}
#'
#'    The frequency \code{\link{dec_pos}} depends on the proportion of positive decisions \code{\link{ppod}}
#'    and
#'    the frequency \code{\link{dec_neg}} depends on the proportion of negative decisions \code{1 - \link{ppod}}.
#'
#'    \item by accuracy (i.e., correspondence of decision to condition):
#'
#'    \code{\link{N} = \link{dec_cor} + \link{dec_err}}
#'
#'    }
#'
#' Each perspective combines 2 pairs of the 4 essential probabilities (hi, mi, fa, cr).
#'
#' When providing probabilities, the population size \code{\link{N}} is a free parameter (independent of the
#' essential probabilities \code{\link{prev}}, \code{\link{sens}}, and \code{\link{spec}}).
#'
#' If \code{\link{N}} is unknown (\code{NA}), a suitable minimum value can be computed by \code{\link{comp_min_N}}.
#'
#' \item Defining probabilities in terms of frequencies:
#'
#' Probabilities \emph{are} -- determine, describe, or are defined as -- the relationships between frequencies.
#' Thus, they can be computed as ratios between frequencies:
#'
#'   \enumerate{
#'
#'   \item prevalence \code{\link{prev}}:
#'
#'   \code{\link{prev} = \link{cond_true}/\link{N}  =  (\link{hi} + \link{mi}) / (\link{hi} + \link{mi} + \link{fa} + \link{cr})}
#'
#'   \item sensitivity \code{\link{sens}}:
#'
#'   \code{\link{sens} = \link{hi}/\link{cond_true}  =  \link{hi} / (\link{hi} + \link{mi})  =  (1 - \link{mirt})}
#'
#'   \item miss rate \code{\link{mirt}}:
#'
#'   \code{\link{mirt} = \link{mi}/\link{cond_true}  =  \link{mi} / (\link{hi} + \link{mi})  =  (1 - \link{sens})}
#'
#'   \item specificity \code{\link{spec}}:
#'
#'   \code{\link{spec} = \link{cr}/\link{cond_false}  =  \link{cr} / (\link{fa} + \link{cr})  =  (1 - \link{fart})}
#'
#'   \item false alarm rate \code{\link{fart}}:
#'
#'   \code{\link{fart} = \link{fa}/\link{cond_false}  =  \link{fa} / (\link{fa} + \link{cr})  =  (1 - \link{spec})}
#'
#'   \item proportion of positive decisions \code{\link{ppod}}:
#'
#'   \code{\link{ppod} = \link{dec_pos}/\link{N}  =  (\link{hi} + \link{fa}) / (\link{hi} + \link{mi} + \link{fa} + \link{cr})}
#'
#'   \item positive predictive value \code{\link{PPV}}:
#'
#'   \code{\link{PPV} = \link{hi}/\link{dec_pos}  =  \link{hi} / (\link{hi} + \link{fa})  =  (1 - \link{FDR})}
#'
#'   \item negative predictive value \code{\link{NPV}}:
#'
#'   \code{\link{NPV} = \link{cr}/\link{dec_neg}  =  \link{cr} / (\link{mi} + \link{cr})  =  (1 - \link{FOR})}
#'
#'   \item false detection rate \code{\link{FDR}}:
#'
#'   \code{\link{FDR} = \link{fa}/\link{dec_pos}  =  \link{fa} / (\link{hi} + \link{fa})  =  (1 - \link{PPV})}
#'
#'   \item false omission rate \code{\link{FOR}}:
#'
#'   \code{\link{FOR} = \link{mi}/\link{dec_neg}  =  \link{mi} / (\link{mi} + \link{cr})  =  (1 - \link{NPV})}
#'
#'   \item accuracy \code{\link{acc}}:
#'
#'   \code{\link{acc} = \link{dec_cor}/\link{N}  =  (\link{hi} + \link{cr}) / (\link{hi} + \link{mi} + \link{fa} + \link{cr})}
#'
#'   \item rate of hits, given accuracy \code{p_acc_hi}:
#'
#'   \code{p_acc_hi = \link{hi}/\link{dec_cor} = (1 - \link{cr}/\link{dec_cor})}
#'
#'   \item rate of false alarms, given inaccuracy \code{p_err_fa}:
#'
#'   \code{p_err_fa = \link{fa}/\link{dec_err} = (1 - \link{mi}/\link{dec_err})}
#'
#'    }
#'
#'    Beware of rounding and sampling issues!
#'    If frequencies are rounded (by \code{round = TRUE} in \code{\link{comp_freq}})
#'    or sampled from probabilities (by \code{sample = TRUE}),
#'    then any probabilities computed from \code{\link{freq}} may differ
#'    from original and exact probabilities.
#'
#' }
#'
#' Functions translating between representational formats:
#' \code{\link{comp_prob_prob}}, \code{\link{comp_prob_freq}},
#' \code{\link{comp_freq_prob}}, \code{\link{comp_freq_freq}}
#' (see documentation of \code{\link{comp_prob_prob}} for details).
#'
#' @param prev The condition's prevalence \code{\link{prev}}
#' (i.e., the probability of condition being \code{TRUE}).
#'
#' @param sens The decision's sensitivity \code{\link{sens}}
#' (i.e., the conditional probability of a positive decision
#' provided that the condition is \code{TRUE}).
#'
#' @param spec The decision's specificity value \code{\link{spec}}
#' (i.e., the conditional probability
#' of a negative decision provided that the condition is \code{FALSE}).
#'
#' @param N The number of individuals in the population.
#' If \code{\link{N}} is unknown (\code{NA}),
#' a suitable minimum value is computed by \code{\link{comp_min_N}}.
#'
#' @param round  Boolean value that determines whether frequency values
#' are rounded to the nearest integer.
#' Default: \code{round = TRUE}.
#'
#' Note: Removed \code{n_digits} parameter:  Number of digits to which frequency values
#' are to be rounded when \code{round = FALSE}.
#' Default: \code{n_digits = 5}.
#'
#' @param sample  Boolean value that determines whether frequency values
#' are sampled from \code{N}, given the probability values of
#' \code{prev}, \code{sens}, and \code{spec}.
#' Default: \code{sample = FALSE}.
#'
#' Note: Sampling uses \code{sample()} and returns integer values.
#'
#' @return A list \code{\link{freq}} containing 11 key frequency values.
#'
#' @examples
#' comp_freq()          # ok, using current defaults
#' length(comp_freq())  # 11 key frequencies
#'
#' # Rounding:
#' comp_freq(prev = .5, sens = .5, spec = .5, N = 1)   # yields fa = 1 (see ?round for reason)
#' comp_freq(prev = .1, sens = .9, spec = .8, N = 10)  # 1 hit (TP, rounded)
#' comp_freq(prev = .1, sens = .9, spec = .8, N = 10, round = FALSE)    # hi = .9
#' comp_freq(prev = 1/3, sens = 6/7, spec = 2/3, N = 1, round = FALSE)  # hi = 0.2857143
#'
#' # Sampling (from probabilistic description):
#' comp_freq_prob(prev = .5, sens = .5, spec = .5, N = 100, sample = TRUE)  # freq values vary
#'
#' # Extreme cases:
#' comp_freq(prev = 1, sens = 1, spec = 1, 100)  # ok, N hits (TP)
#' comp_freq(prev = 1, sens = 1, spec = 0, 100)  # ok, N hits
#' comp_freq(prev = 1, sens = 0, spec = 1, 100)  # ok, N misses (FN)
#' comp_freq(prev = 1, sens = 0, spec = 0, 100)  # ok, N misses
#' comp_freq(prev = 0, sens = 1, spec = 1, 100)  # ok, N correct rejections (TN)
#' comp_freq(prev = 0, sens = 1, spec = 0, 100)  # ok, N false alarms (FP)
#'
#' # Watch out for:
#' comp_freq(prev = 1, sens = 1, spec = 1, N = NA)  # ok, but warning that N = 1 was computed
#' comp_freq(prev = 1, sens = 1, spec = 1, N =  0)  # ok, but all 0 + warning (extreme case: N hits)
#' comp_freq(prev = .5, sens = .5, spec = .5, N = 10, round = TRUE)   # ok, rounded (see mi and fa)
#' comp_freq(prev = .5, sens = .5, spec = .5, N = 10, round = FALSE)  # ok, not rounded
#'
#' # Ways to fail:
#' comp_freq(prev = NA,  sens = 1, spec = 1,  100)   # NAs + warning (prev NA)
#' comp_freq(prev = 1,  sens = NA, spec = 1,  100)   # NAs + warning (sens NA)
#' comp_freq(prev = 1,  sens = 1,  spec = NA, 100)   # NAs + warning (spec NA)
#' comp_freq(prev = 8,  sens = 1,  spec = 1,  100)   # NAs + warning (prev beyond range)
#' comp_freq(prev = 1,  sens = 8,  spec = 1,  100)   # NAs + warning (sens beyond range)
#'
#' @family functions computing frequencies
#'
#' @seealso
#' \code{\link{comp_freq_prob}} corresponding wrapper function;
#' \code{\link{num}} contains basic numeric variables;
#' \code{\link{init_num}} initializes basic numeric variables;
#' \code{\link{freq}} contains current frequency information;
#' \code{\link{prob}} contains current probability information;
#' \code{\link{comp_prob}} computes current probability information;
#' \code{\link{comp_complement}} computes a probability's complement;
#' \code{\link{comp_comp_pair}} computes pairs of complements;
#' \code{\link{comp_complete_prob_set}} completes valid sets of probabilities;
#' \code{\link{comp_min_N}} computes a suitable population size \code{\link{N}} (if missing).
#'
#' @export

## comp_freq: Definition --------

comp_freq <- function(prev = num$prev, sens = num$sens, spec = num$spec, # 3 essential probabilities (NOT: mirt, fart)
                      N = num$N,       # default N
                      round = TRUE,    # round freq values to integers?
                      # n_digits = 5,  # digits to which non-rounded freq are rounded (REMOVED: only round values SHOWN, not computed!)
                      sample = FALSE   # sample freq values from probabilities?
) {

  ## (0) Initialize freq:
  freq <- init_freq()  # initialize freq (containing only NA values)

  ## (1) Only if 3 essential probabilities are valid:
  if (is_valid_prob_set(prev = prev, sens = sens, spec = spec)) {
    # if (is_valid_prob_triple(prev = prev, sens = sens, spec = spec)) {

    ## (2) Compute missing fart or spec (4th argument) value (if applicable):
    # cur.spec.fart <- comp_comp_pair(spec, fart)  # (do only when needed)
    # spec <- cur.spec.fart[1]  # 1st argument
    # fart <- cur.spec.fart[2]  # 2nd argument

    ## (3) Issue a warning if essential probabilities describe an extreme case:
    is_extreme_prob_set(prev = prev, sens = sens, spec = spec)  # prints a warning if TRUE

    ## (4) Compute missing population size value N (if applicable):
    if (is.na(N)) {

      N <- comp_min_N(prev = prev, sens = sens, spec = spec, min_freq = 1)

      warning(paste0("Unknown population size N. A suitable minimum value of N = ", N, " was computed."))
    }

    ## (5) Main: Determine values of freq: ------
    freq$N <- N  # copy N from argument OR num (input)
    # sample <- FALSE  # sample freq with essential prob [+++ here now +++]

    if (!sample){ # NO sampling (default):

      # (5a): Using exact probability values (i.e., no sampling): ----

      # A. In 2 stages:
      # (a) Number of cond_true vs. cond_false cases (by condition):
      if (round) {
        freq$cond_true <- round((N * prev), 0)  # 1a. cond_true  = N x prev [rounded to nearest integer]
      } else {
        freq$cond_true <- (N * prev)            # 1b. cond_true  = N x prev [not rounded]
      }
      freq$cond_false <- (N - freq$cond_true)   # 2. cond_false = complement of cond_true (to N)

      # (b) Values of 4 SDT combinations/cases/cells:
      if (round) {
        freq$hi <- round((sens * freq$cond_true), 0)   # a1. N of hi [rounded to nearest integer]
      } else {
        freq$hi <- (sens * freq$cond_true)             # a2. N of hi [not rounded]
      }
      freq$mi <- (freq$cond_true - freq$hi)            # b.  N of mi = complement of hi (to cond_true)

      if (round) {
        freq$cr <- round((spec * freq$cond_false), 0)  # c1. N of cr [rounded to nearest integer]
      } else {
        freq$cr <- (spec * freq$cond_false)            # c2. N of cr [not rounded]
      }
      freq$fa <- (freq$cond_false - freq$cr)           # d.  N of fa - complement of cr (to cond_false)

    } else { # sample() from N by prev, sens, and spec:

      # (5b): Sampling by probability values: ----

      # a. Sampling cond_true from N with prev:
      freq$cond_true  <- sum(sample(x = c(1, 0), size = N, replace = TRUE, prob = c(prev, 1-prev)))
      freq$cond_false <- (N - freq$cond_true)  # derived as complement

      # b. Sampling hi from cond_true with sens:
      freq$hi <- sum(sample(x = c(1, 0), size = freq$cond_true, replace = TRUE, prob = c(sens, 1-sens)))
      freq$mi <- (freq$cond_true - freq$hi)  # derived as complement

      # c. Sampling cr from cond_false with spec:
      freq$cr <- sum(sample(x = c(1, 0), size = freq$cond_false, replace = TRUE, prob = c(spec, 1-spec)))
      freq$fa <- (freq$cond_false - freq$cr)  # derived as complement

    } # else sample.

    # B. Derived values:
    # (c) Number of positive vs. negative decisions (by decision):
    freq$dec_pos <- freq$hi + freq$fa  # 1. positive decisions (true & false positives)
    freq$dec_neg <- freq$mi + freq$cr  # 2. negative decisions (false & true negatives)

    # (d) Accuracy/Correspondence of decision to condition (by correspondence):
    freq$dec_cor <- freq$hi + freq$cr  # N of correct decisions
    freq$dec_err <- freq$mi + freq$fa  # N of erroneous decisions


    ## (6) Check current frequency values for consistency:
    tol <- .0001  # tolerance threshold for mismatch of sums

    if (#isTRUE(all.equal(freq$N, (freq$hi + freq$mi + freq$fa + freq$cr), tolerance = tol)) &&
      (abs(freq$N - (freq$hi + freq$mi + freq$fa + freq$cr)) > tol) ||
      (abs(freq$cond_true - (freq$hi + freq$mi)) > tol)             ||
      (abs(freq$cond_false - (freq$fa + freq$cr)) > tol)            ||
      # (abs(dec_pos - (hi + fa)) > tol)               ||  # (computed as such above)
      # (abs(dec_neg - (mi + cr)) > tol)               ||  # (computed as such above)
      # (abs(dec_cor - (hi + cr)) > tol)               ||  # (computed as such above)
      # (abs(dec_err - (mi + fa)) > tol)               ||  # (computed as such above)
      (abs(freq$N - (freq$cond_true + freq$cond_false)) > tol)      ||
      (abs(freq$N - (freq$dec_pos + freq$dec_neg)) > tol)           ||
      (abs(freq$N - (freq$dec_cor + freq$dec_err)) > tol)           ) {

      warning("Current frequencies do NOT add up to N.")
    }

  } # if (is_valid(prev, sens, spec, fart))

  ## (7) Round non-rounded freq (to n_digits):
  ## if (!round) { freq <- lapply(X = freq, FUN = round, digits = n_digits) }
  ## (REMOVED: only round values SHOWN, not computed!)

  ## (8) Return entire list freq:
  return(freq)

}

## Check:

# comp_freq()                  # ok, using current defaults
# length(comp_freq())          # 11
#
# # Rounding effects:
# comp_freq(prev = .5, sens = .5, spec = .5, N = 1)   # yields fa = 1 (see ?round for reason)
# comp_freq(prev = .1, sens = .9, spec = .8, N = 10)  # 1 hit (TP, rounded)
# comp_freq(prev = .1, sens = .9, spec = .8, N = 10, round = FALSE)  # .9 hit
# comp_freq(prev = 1/3, sens = 6/7, spec = 2/3, N = 1, round = FALSE)  # hi = 0.2857143
# # comp_freq(prev = 1/3, sens = 6/7, spec = 2/3, N = 1, round = FALSE, n_digits = 3)  # hi = 0.286 # Removed n_digits.
# # comp_freq(prev = 1/3, sens = 6/7, spec = 2/3, N = 1, round = FALSE, n_digits = 1)  # hi = 0.3   # Removed n_digits.
#
# # Extreme cases:
# comp_freq(prev = 1, sens = 1, spec = 1, 100)  # ok, N hits (TP)
# comp_freq(prev = 1, sens = 1, spec = 0, 100)  # ok, N hits
# comp_freq(prev = 1, sens = 0, spec = 1, 100)  # ok, N misses (FN)
# comp_freq(prev = 1, sens = 0, spec = 0, 100)  # ok, N misses
# comp_freq(prev = 0, sens = 1, spec = 1, 100)  # ok, N correct rejections (TN)
# comp_freq(prev = 0, sens = 1, spec = 0, 100)  # ok, N false alarms (FP)
#
# # Watch out for:
# comp_freq(prev = 1, sens = 1, spec = 1, N = NA)  # ok, but warning that N = 1 was computed
# comp_freq(prev = 1, sens = 1, spec = 1, N =  0)  # ok, but all 0 + warning (extreme case: N hits)
# comp_freq(prev = .5, sens = .5, spec = .5, N = 10, round = TRUE)   # ok, but rounded (increasing errors: mi and fa)
# comp_freq(prev = .5, sens = .5, spec = .5, N = 10, round = FALSE)  # ok, but not rounded
#
# # Ways to fail:
# comp_freq(prev = NA,  sens = 1, spec = 1,  100)  # NAs + warning (prev NA)
# comp_freq(prev = 1,  sens = NA, spec = 1,  100)  # NAs + warning (sens NA)
# comp_freq(prev = 1,  sens = 1,  spec = NA, 100)  # NAs + warning (spec NA)
# comp_freq(prev = 8,  sens = 1,  spec = 1,  100)  # NAs + warning (prev beyond range)
# comp_freq(prev = 1,  sens = 8,  spec = 1,  100)  # NAs + warning (sens beyond range)


## (3) Apply to initialize freq: ----------

## freq: Documentation ------

#' List current frequency information.
#'
#' \code{freq} is a list of named numeric variables
#' containing 11 key frequencies (and their values):
#'
#' \enumerate{
#'
#'  \item the population size \code{\link{N}}
#'
#'  \item the number of cases for which \code{\link{cond_true}}
#'  \item the number of cases for which \code{\link{cond_false}}
#'
#'  \item the number of cases for which \code{\link{dec_pos}}
#'  \item the number of cases for which \code{\link{dec_neg}}
#'
#'  \item the number of cases for which \code{\link{dec_cor}}
#'  \item the number of cases for which \code{\link{dec_err}}
#'
#'  \item the number of true positives, or hits \code{\link{hi}}
#'  \item the number of false negatives, or misses \code{\link{mi}}
#'  \item the number of false positives, or false alarms \code{\link{fa}}
#'  \item the number of true negatives, or correct rejections \code{\link{cr}}
#'
#' }
#'
#' These frequencies are computed from basic parameters
#' (contained in \code{\link{num}}) and computed by using
#' \code{\link{comp_freq}}.
#'
#' The list \code{freq} is the frequency counterpart
#' to the list containing probability information \code{\link{prob}}.
#'
#' Natural frequencies are always expressed in
#' relation to the current population of
#' size \code{\link{N}}.
#'
#' Key relationships between frequencies and probabilities
#' (see documentation of \code{\link{comp_freq}} or \code{\link{comp_prob}} for details):
#'
#' \itemize{
#'
#'   \item Three perspectives on a population:
#'
#'   by condition / by decision / by accuracy.
#'
#'   \item Defining probabilities in terms of frequencies:
#'
#'   Probabilities can be computed as ratios between frequencies, but beware of rounding issues.
#'
#' }
#'
#' Functions translating between representational formats:
#' \code{\link{comp_prob_prob}}, \code{\link{comp_prob_freq}},
#' \code{\link{comp_freq_prob}}, \code{\link{comp_freq_freq}}
#' (see documentation of \code{\link{comp_prob_prob}} for details).
#'
#' Visualizations of current frequency information
#' are provided by \code{\link{plot_prism}} and
#' \code{\link{plot_icons}}.
#'
#' @examples
#' freq <- comp_freq()  # initialize freq to default parameters
#' freq                 # show current values
#' length(freq)         # 11 known frequencies
#' names(freq)          # show names of known frequencies
#'
#' @family lists containing current scenario information
#'
#' @seealso
#' \code{\link{comp_freq}} computes current frequency information;
#' \code{\link{num}} contains basic numeric variables;
#' \code{\link{init_num}} initializes basic numeric variables;
#' \code{\link{prob}} contains current probability information;
#' \code{\link{num}} contains basic numeric parameters;
#' \code{\link{init_num}} initializes basic numeric parameters;
#' \code{\link{txt}} contains current text information;
#' \code{\link{init_txt}} initializes text information;
#' \code{\link{pal}} contains current color information;
#' \code{\link{init_pal}} initializes color information.
#'
#' @export

## freq: Definition --------

freq <- comp_freq()  # initialize freq to default parameters

## Check:
# freq               # show current values
# length(freq)       # 11 known frequencies
# names(freq)        # show names of known frequencies



## comp_freq_type: Determine the type of a named frequency (freq):  -------

comp_freq_type <- function(fname, lbl_txt = txt) {

  f_type <- "typeless"  # initialize

  # (1) Define types of all known frequencies:

  # (a) Using basic names:
  # freq_types <- c("popu", rep("cond", 2), rep("dec", 2), rep("accu", 2), rep("cell", 4))

  # (b) Using labels defined in lbl_txt:
  freq_types <- c(lbl_txt$popu_lbl,
                  rep(lbl_txt$cond_lbl, 2),
                  rep(lbl_txt$dec_lbl, 2),
                  rep(lbl_txt$acc_lbl, 2),
                  rep(lbl_txt$sdt_lbl, 4))
  # freq_types

  # (2) Map freq to name in freq_types:
  if (fname %in% names(freq)) { # if freq corresponds to named frequency in freq:
    ix <- which(names(freq) == fname)  # index in freq
    # print(ix)
    f_type <- freq_types[ix]
  }

  return(f_type)  # return f_type (as character)

}

## Check:
# comp_freq_type("N")
# comp_freq_type("cond_false")
# comp_freq_type("dec_neg")
# comp_freq_type("dec_err")
# comp_freq_type("cr")

## Using alternative text labels:
# comp_freq_type("cond_true", lbl_txt = txt_TF) # "Truth"
# comp_freq_type("dec_pos", lbl_txt = txt_TF)   # "Test"

## Note:
# comp_freq_type(N)        # typeless (as function requires name, NOT a value)
# comp_freq_type("false")  # typeless (as full name is required)




## comp_freq_col: Determine the color of a named frequency (freq) in current color palette (col_pal):  ----------

comp_freq_col <- function(fname,
                          col_pal = pal,
                          col = NA  # primary color
) {

  # initialize:
  col_name <- NA
  f_col <- NA

  if (!is.na(col)) { # if col is specified:

    f_col <- col  # use it!

  } else {  # figure out f_col from fname and col_pal:

    # (A) if freq corresponds to named frequency in freq:
    if (fname %in% names(freq)) {

      ## Derive current values corresponding to freq:
      ix <- which(names(freq) == fname)  # index in freq

      ## (a) Value of frequency in freq:
      # f_val <- freq[ix]

      ## (b) Type of frequency:
      # f_type <- comp_freq_type(fname)  # see helper function (defined in init_freq_num.R)

      # (c) Color of frequency:

      # Note that names(freq) were sometimes longer than names(pal):
      # If fname contains a dot (.):  Use only the name part after the dot:
      if (any(grep(pattern = "\\.", x = fname))) {

        nameparts <- unlist(strsplit(fname, split = "\\."))

        part_1 <- nameparts[1]  # 1st part of fname
        part_2 <- nameparts[2]  # 2nd part of fname
        col_name <- part_2  # 2nd part of fname corresponds to name of color

        # if (col_name == "true") { col_name <- "cor" }

      } else {
        col_name <- fname  # col_name corresponds to fname (for frequencies)
      }

      # print(col_name)

    }

    # (B) Find color value of col_name in current color col_pal:
    if (col_name %in% names(col_pal)) { # if col_name corresponds to a color name in col_pal
      f_col <- col_pal[col_name]        # use this color to fill box
    } else {
      f_col <- grey(.95, .50)  # use some default color (e.g., "white")
    }

  } # else.

  # print(f_col)
  return(f_col)

}

## Check:

# comp_freq_col("N")
# comp_freq_col("hi")
# comp_freq_col("cond_true")
# comp_freq_col("dec_pos")
# comp_freq_col("dec_cor")
#
# comp_freq_col("default")          # use default color
# comp_freq_col("N", col = "gold")  # "gold"
# comp_freq_col("nn", col = "gold") # "gold"


## (*) Done: -----------

## - etc.

## (+) ToDo: -----------

## - etc.

## eof. ------------------------------------------
hneth/riskyr documentation built on Feb. 18, 2024, 6:01 p.m.