R/tableANOVA.R

Defines functions tableANOVA

Documented in tableANOVA

#' Create a Table of ANOVA results
#'
#' Automatically generates HTML table with results for one-way or two-way ANOVAs.
#'
#' @param audioData A data.frame generated by the autoExtract() function.
#' @param by A character vector indicating the name of the factor(s).
#' @param measure Name of the dependent variable.
#' @param nameMeasure Optional relabelling of dependent variable for the output table. If no value is provided, the original variable name is used.
#' @param figureNumber An integer indicating the figure number to create the title for the table. Default corresponds to 1.
#' @return HTML table showing the ANOVA results in APA formatting style.
#' @examples
#' tableANOVA(testAudioData, by = c("Condition", "Dimension"), measure = "duration")
#'
#' @importFrom stats as.formula aov
#' @importFrom stringr str_replace_all
#' @importFrom kableExtra kable_classic footnote
#' @importFrom knitr kable
#' @export


tableANOVA <- function(audioData, by = c(), measure = "duration", nameMeasure = c(), figureNumber = 1){
  by <- as.vector(by)
  if(!is.data.frame(audioData)) stop("audioData should be a data.frame produced by autoExtract")
  if(length(measure) != 1 && !measure %in% colnames(audioData)) {
    stop("measure should be present on audioData")
  }
  if(sum(!by %in% colnames(audioData)) > 0){
    stop(paste(by[which(!by %in% colnames(audioData))], "not found in audioData"))
  }
  if(!is.numeric(audioData[,measure])){
    stop("Variable selected using measure is not numeric")
  }
  if(length(by) == 0){
    stop("No by values provided.")
  }
  if(!(all(apply(audioData[, tolower(colnames(audioData)) %in% tolower(by), drop = FALSE], 2, is.factor)) || all(apply(audioData[, tolower(colnames(audioData)) %in% tolower(by), drop = FALSE], 2, is.character)))){
    stop("Variables selected using by are not factors")
  }





  #If no custom name provided for the measure, use the measure name
  if(length(nameMeasure) == 0 || !is.character(nameMeasure)){
    nameMeasure <- measure
  }



  #If one-way
  if(length(by) == 1){
    #Compute one way anova
    formula = as.formula(paste(measure, "~", by))
    #Summarize results
    AnovaTestData <- summary(aov(formula, audioData))[[1]]
    #Create descrtiption table from the test data
    descriptionTable <- data.frame(Source = rownames(AnovaTestData), df = AnovaTestData$Df, SS = round(AnovaTestData$`Sum Sq`,2), MS = round(AnovaTestData$`Mean Sq`, 2), F = round(AnovaTestData$`F value`, 2), p = round(AnovaTestData$`Pr(>F)`, 3))
    #Create star notation for p values
    descriptionTable2 <- descriptionTable[1,]
    if(length(descriptionTable2[descriptionTable2$p < 0.05, "p"]) > 0)
      descriptionTable2[descriptionTable2$p < 0.05, "sig"] <- paste(descriptionTable2[descriptionTable2$p < 0.05, "p"], "(*)")
    if(length(descriptionTable2[descriptionTable2$p < 0.01, "p"]) > 0)
      descriptionTable2[descriptionTable2$p < 0.01, "sig"] <- paste(descriptionTable2[descriptionTable2$p < 0.01, "p"], "(**)")
    if(length(descriptionTable2[descriptionTable2$p < 0.001, "p"]) > 0)
      descriptionTable2[descriptionTable2$p < 0.001, "sig"] <- paste(descriptionTable2[descriptionTable2$p < 0.001, "p"], "(***)")
    if(length(descriptionTable2[descriptionTable2$p >= 0.05, "p"]) > 0)
      descriptionTable2[descriptionTable2$p >= 0.05, "sig"] <- paste(descriptionTable2[descriptionTable2$p >= 0.05, "p"], "")

    descriptionTable[1,]$p <- descriptionTable2$sig

    descriptionTable <- rbind(descriptionTable, c("Total", sum(descriptionTable[,2]), sum(descriptionTable[,3]), NA, NA, NA))
    descriptionTable[2,which(is.na(descriptionTable[2,]))] <- " "
    descriptionTable[3,which(is.na(descriptionTable[3,]))] <- " "

    columnNames <- colnames(descriptionTable)
    rowNames <- descriptionTable[,1]
    descriptionTable <- data.frame(lapply(descriptionTable, function(x) str_replace_all(x, "0\\.", ".")))
    colnames(descriptionTable) <- columnNames
    descriptionTable[,1] <- rowNames
    #Format table using kable extra
    descriptionTable <- kable_classic(kable(
      descriptionTable,
      format = "html",
      booktabs = TRUE,
      caption = paste0("Figure ", figureNumber, ". One-Way Analysis of Variance of ", nameMeasure, " by ", by)
    ), full_width = F, html_font = "Cambria")
  }
  #If two-way
  else if(length(by) == 2){
    #Compute two way anova
    formula = as.formula(paste(measure, "~", by[1], "*", by[2]))
    AnovaTestData <- summary(aov(formula, audioData))[[1]]
    #Build table from summarized results
    descriptionTable <- data.frame(Source = rownames(AnovaTestData), df = AnovaTestData$Df, SS = round(AnovaTestData$`Sum Sq`,2), MS = round(AnovaTestData$`Mean Sq`, 2), F = round(AnovaTestData$`F value`, 2), p = round(AnovaTestData$`Pr(>F)`, 3))
    descriptionTable2 <- descriptionTable[1:3,]
    #Create star notation for p values
    if(length(descriptionTable2[descriptionTable2$p < 0.05, "p"]) > 0)
      descriptionTable2[descriptionTable2$p < 0.05, "sig"] <- paste(descriptionTable2[descriptionTable2$p < 0.05, "p"], "(*)")
    if(length(descriptionTable2[descriptionTable2$p < 0.01, "p"]) > 0)
      descriptionTable2[descriptionTable2$p < 0.01, "sig"] <- paste(descriptionTable2[descriptionTable2$p < 0.01, "p"], "(**)")
    if(length(descriptionTable2[descriptionTable2$p < 0.001, "p"]) > 0)
      descriptionTable2[descriptionTable2$p < 0.001, "sig"] <- paste(descriptionTable2[descriptionTable2$p < 0.001, "p"], "(***)")
    if(length(descriptionTable2[descriptionTable2$p >= 0.05, "p"]) > 0)
      descriptionTable2[descriptionTable2$p >= 0.05, "sig"] <- paste(descriptionTable2[descriptionTable2$p >= 0.05, "p"], "")

    descriptionTable[1:3,]$p <- descriptionTable2$sig
    # produce final description table
    descriptionTable <- rbind(descriptionTable, c("Total", sum(descriptionTable[,2]), sum(descriptionTable[,3]), NA, NA, NA))
    descriptionTable$Source[3] <- "Interaction"
    descriptionTable[2,which(is.na(descriptionTable[2,]))] <- " "
    descriptionTable[3,which(is.na(descriptionTable[3,]))] <- " "
    descriptionTable[4,which(is.na(descriptionTable[4,]))] <- " "
    descriptionTable[5,which(is.na(descriptionTable[5,]))] <- " "

    columnNames <- colnames(descriptionTable)
    rowNames <- descriptionTable[,1]
    descriptionTable <- data.frame(lapply(descriptionTable, function(x) str_replace_all(x, "0\\.", ".")))
    colnames(descriptionTable) <- columnNames
    descriptionTable[,1] <- rowNames
    # Format final table using kable extra
    descriptionTable <- kable_classic(kable(
      descriptionTable,
      format = "html",
      booktabs = TRUE,
      caption = paste0("Figure ", figureNumber, ". Two-Way Analysis of Variance of ", nameMeasure, " by ", paste(by[1], "and", by[2]))
    ), full_width = F, html_font = "Cambria")
  }
  #return error
  else{
    stop("Error, incorrect by argument. By should have minimum length of 1 and maximum length of 2.")
  }

  #Add footnote with p values
  descriptionTable <- footnote(descriptionTable, general ="* p < .05, ** p < .01, *** p < .001", threeparttable = TRUE, footnote_as_chunk = TRUE)
  return(descriptionTable)
}

Try the voiceR package in your browser

Any scripts or data that you put into this service are public.

voiceR documentation built on Sept. 13, 2023, 1:07 a.m.