R/FormatData.R

Defines functions FormatData

Documented in FormatData

#' Format results for documents and manuscripts
#' 
#' This function is used to produce a string from numbers describing 
#' results (value and range) for documents and manuscripts. 
#' 
#' @details The idea of this function is to take a number and range 
#' (optional) and put it into the suitable format for writing purposes 
#' using the appropriate format, range description, and units. 
#' 
#' For specific applications it is useful to right wrapper 
#' functions to save having to spell out all the options. 
#' 
#' The punctuation generally follows the Lancet style.    
#' 
#' @param estimate Numeric value we are reporting.
#' @param lower Lower value of the number we are reporting. Optional so 
#' NULL by default. Can just present the lower bound, e.g., to present 
#' "10 (SD 2)"
#' @param upper Upper value of the number we are reporting. Optional so 
#' NULL by default. 
#' @param places Integer indicating the number of decimal places (in round).
#' Negative values are allowed and means rounding to a power of ten, so for 
#' example round(x, digits = -2) rounds to the nearest hundred. 
#' @param prefix String to put in front of numbers. Primarily used for 
#' adding "$" or "A$" for monetary values.     
#' @param suffix String to put at the end of numeric values. Primarily used
#' used for adding percent symbol. 
#' @param units String to place after estimate for units. 
#' @param rangestr String to put in front of the range. For example 
#' "range: ", "95 percent CI: ".
#' @param rangeto String to link the lower and upper value in the range.
#' Default is an en-dash but could be ":", " to ", etc.
#' @param rangebracket Vector of two string to separate estimate from range. 
#' Default is round brackets c(" (",")") but could use other brackets or 
#' commas c(", ", ",") or something else. 
#' @param rangeappend Append prefix and suffix to both lower and upper 
#' ("both) or just prefix to lower and suffix to upper ("single"). 
#' @param thousands String to separate estimates by thousands. Default is 
#' a comma "," but can be a space " ". 
#' @param decimal String to show decimal only does lower or midline. 
#' Default is "." but Lancet uses a midline decimal.
#' @param tail String to attach to the end of the overall string. NOT sure
#' if this is useful or not.
#' 
#' @return String with the estimate and range in appropriate format.
#' 
#' @author Richard T Gray, \email{Rgray@kirby.unsw.edu.au}
#' 
#' @examples 
#' FormatData(1951508)
#' FormatData(1951508, prefix = "US$")
#' 
#' FormatData(36.7858, 5.8124, rangestr = "SD ")
#' FormatData(36.7858, 5.8124, units = "copies/ml", rangestr = "SD ")
#' 
#' FormatData(1235.45, 179.3, 12707.5, prefix = "A$", rangeappend = "both", 
#' rangeto = " to ", rangestr = "range: ")
#' 
#' FormatData(0.84, 0.71, 0.98, decimal = "mid", rangestr = "95% CI: ") 
#' FormatData(0.84, 0.71, 0.98, rangebracket = c(", ",","), 
#' rangestr = "95% CI: ", tail = paste0(" p=", toString(0.03)))
#' 
#' FormatData(84.3, 72.456, 98.123245, suffix = "%")
#' FormatData(84.3, 72.456, 98.123245, suffix = "%", units = "per year", 
#' rangeappend = "both", rangeto = " to ")
#' 
#' @export
#' @import stringr
#' 
FormatData <- function(estimate, lower = NA, upper = NA, places = NULL, 
  prefix = "", suffix = "", units = "", rangestr = "", rangeto = "\u2012",
  rangebracket = c(" (",")"), rangeappend = c("single", "both"), 
  thousands = c(",", " "), decimal = c("low","mid"), tail = "") {
  
  # Setup defaults - "mid" specifies a mid-line decimal
  decimal <- match.arg(decimal)
  decimal <- ifelse(decimal == "low", ".", "\U00B7")
  thousands <- match.arg(thousands)
  rangeappend <- match.arg(rangeappend)
  
  # Round values appropriately
  if (is.null(places[1])) {
    
    # Change depending on estimate value using a function
    ValuePlaces <- function(value) {
      if (is.na(value)) {
        places <- 0
      } else if (value < 10) {
        places <- 2
      } else if (value >= 10 && value < 1000) {
        places <- 1
      } else if (value >= 1000 && value < 10000) {
        places <- 0
      } else {
        places <- -2
      }
      
      return(places)
    }
    
    # Round estimate and range depending on value
    estPlaces <- ValuePlaces(estimate)
    lowPlaces <- ValuePlaces(lower)
    upPlaces <- ValuePlaces(upper)
    
  } else {
    # Round estimate and range using places
    estPlaces <- places
    lowPlaces <- places
    upPlaces <- places
  } 
  
  # Convert values and range into strings - TODO may need to add format as 
  # a variable to specify scientific notation. 
  estStr <- formatC(round(estimate, estPlaces), digits = max(estPlaces, 0), 
    big.mark = thousands, decimal.mark = decimal, format = "f")
  lowStr <- ifelse(is.na(lower), "", formatC(round(lower, lowPlaces), 
    digits = max(lowPlaces, 0), big.mark = thousands, decimal.mark = decimal, 
    format = "f"))
  upStr <- ifelse(is.na(upper), "", formatC(round(upper, upPlaces), 
    digits = max(upPlaces, 0), big.mark = thousands, decimal.mark = decimal, 
    format = "f"))
  
  # Add suffixes and prefixes
  if (units[1] != "") {
    estStr <- paste0(prefix, estStr, suffix, " ", units) 
  } else {
    estStr <- paste0(prefix, estStr, suffix)
  }
  
  # Setup range string
  if (lowStr[1] == "" && upStr[1] == "") {
  # No range
   rangeString <- ""
  } else if (upStr[1] == "") {
    # Only lower bound as a single value
    rangeString <- paste0(rangebracket[1], rangestr, prefix, lowStr, 
      suffix, rangebracket[2])
  } else {
    # Full range
    if (rangeappend == "single") {
      rangeString <- paste0(rangebracket[1], rangestr, prefix, lowStr,
        rangeto, upStr, suffix, rangebracket[2])
    } else {
      rangeString <- paste0(rangebracket[1], rangestr, prefix, lowStr,
        suffix, rangeto, prefix, upStr, suffix, rangebracket[2])
    }
  }
  
  # Create and return final string
  finalStr <- paste0(estStr, rangeString, tail)
  return(finalStr)
} 
leftygray/LeftysRpkg documentation built on Feb. 11, 2024, 5:13 p.m.