R/age_ranges.R

Defines functions age_ranges

Documented in age_ranges

#' roxygen documentation
#'
#' age_ranges
#'
#' Function to derive a range table of taxon names from a
#' stratigraphic occurrence dataset. The default behaviour
#' is to return a total range table - the oldest FAD and
#' youngest LAD for each taxon (max), but the function can
#' also return the minimum range - youngest FAD and oldest
#' LAD (min), or the uncertainty bounds on each FAD and
#' LAD - the two oldest FADs and two youngest LADs (bounds).
#' The names for which ranges are derived are specified by
#' the taxononmy argument, but multiple elements can be
#' given here, allowing taxonomic range for higher clades
#' to also be returned.
#' @param data A three column dataframe comprising one or
#' more character columns of taxonomic names, a numeric
#' column of FADs and a numeric column of LADs
#' @param taxonomy A character vector corresponding to one or
#' more of the taxonomic name columns in data
#' @param srt A character vector of length one specifying the
#' FAD column in data
#' @param end A character vector of length one specifying the
#' LAD column in data
#' @param mode A character vector of length one specifying
#' the type of range table to return: one of max, min or
#' bounds. If not specified by the user, the function
#' behaviour will default to max
#' @return A dataframe containing at least four columns:
#' taxon name, FAD, LAD and the taxonomic rank. If taxonomy
#' is of length one, taxonomic rank will be a vector of
#' identical names. If mode = "bounds", there will be two
#' pairs of age columns, denoting the upper and lower bounds
#' on the FAD and LAD for each taxon name
#' @export

age_ranges <- function(data, taxonomy = "genus", srt = "max_ma", end = "min_ma", mode = "max") {

  # check arguments
  if(!is.data.frame(data)) {
    stop("Data should be a dataframe")
  }
  if(!all(c(taxonomy, srt, end) %in% colnames(data))) {
    stop("One or more of taxonomy, srt or end are not colnames in data")
  }
  if(!all(mode %in% c("max", "min", "bounds"))) {
    stop("Mode must be one of the following: max, min, bounds")
  }
  if(length(mode) > 1) {
    stop("Mode must be one of the following: max, min, bounds")
  }
  if(class(data[,srt]) != "numeric" | class(data[,end]) != "numeric") {
    stop("Columns srt and end must be numeric")
  }
  if(any(is.na(data[,srt])) | any(is.na(data[,end]))) {
    stop("One or more of the ages is NA")
  }
  if(any(data[,srt] < data[,end])) {
    stop("One or more maximum ages are smaller than their corresponding minimum ages")
  }

  # for a single rank
  if(length(taxonomy) == 1) {

    # add a small constant to the FAD to prevent errors in zero-range ages (i.e. FAD == LAD)
    data[,srt] <- data[,srt] + 0.1
    # reformat for indexing
    data <- cbind.data.frame(c(data[,taxonomy], data[,taxonomy]), c(data[,srt], data[,end]))
    data <- unique(data[complete.cases(data),])
    data <- data[order(data[,1], data[,2], decreasing = c(FALSE, TRUE), method = "radix"),]
    # unique positions (FAD uncertainty will be the two oldest unique FADs, same principle with LADS), achieved by ordering and indexing
    fad <- which(!duplicated(data[,1]))
    names(fad) <- data[fad,1]
    lad <- table(data[,1])
    lad <- lad[order(match(names(lad), names(fad)))]
    lad <- cumsum(lad)
    ages <- cbind.data.frame(data[fad,1], data[fad,2], data[(fad + 1),2], data[(lad - 1),2], data[lad,2], taxonomy)
    colnames(ages) <- c("taxon", "FAD_early", "FAD_late", "LAD_early", "LAD_late", "level")
    # remove constant
    ages[,"FAD_early"] <- ages[,"FAD_early"] - 0.1
    ages[,"FAD_late"] <- ages[,"FAD_late"] - 0.1
    if(mode == "min") {
      ages <- ages[,c("taxon", "FAD_late", "LAD_early", "level")]
      colnames(ages) <- c("taxon", "FAD", "LAD", "level")
    }
    if(mode == "max") {
      ages <- ages[,c("taxon", "FAD_early", "LAD_late", "level")]
      colnames(ages) <- c("taxon", "FAD", "LAD", "level")
    }

    # for multiple ranks
  } else {
    ages <- list()
    for(i in 1:length(taxonomy)) {
      ages[[i]] <- age_ranges(data = data, taxonomy = taxonomy[i], srt = srt, end = end, mode = mode)
    }
    ages <- do.call(rbind.data.frame, ages)
  }
  return(ages)
}
jf15558/FAU.JFS documentation built on Jan. 21, 2022, 6:52 a.m.