Formatting P values

For printing ANOVA or regression coefficients tables

This post on R bloggers describes a handy function for formatting really small P values in ANOVA tables (more than 3 decimal places) with \(<0.001\). I find this easier to read when I need to present a formatted table, e.g. in teaching.

The original function doesn’t cover all ways of creating ANOVA tables in R so I have extended the function to cover more cases. The fixp function below will work for ANOVA tables (x) generated by anova(lm(...)) and summary(aov(lm(...))), as well as the model coefficients table generated by coef(summary(lm(...))).

A function to format P values

fixp <- function(x, dig=3){

# Convert to a data frame
  if(is.data.frame(x) | is.matrix(x)){
  x <- as.data.frame(x)
  } else {
  x <- as.data.frame(x[[1]])
  }

# Check column order  
  if(substr(names(x)[ncol(x)],1,2) != "Pr"){
    warning("The name of the last column didn't start with Pr. This may indicate that p-values weren't in the last row, and thus, that this function is inappropriate.")
    }
    
# Round P values to "dig" decimal places, default 3     
  x[,ncol(x)] <- round(x[,ncol(x)], dig)

#  
  for(i in 1:nrow(x)){
    if(x[i,ncol(x)] == 0 & !is.na(x[i,ncol(x)])){
      x[i,ncol(x)] <- paste0("<0.", paste0(rep(0,dig-1), collapse=""), "1")
      }
  }
  x
}

The main modification to the original function is to expand the conversion of x to a data frame to accept lists and matrices. summary(aov(lm(...))) creates an object with class summary.aov which is a list and the coefficients table is a matrix. Although anova(lm(...)) creates a data frame that will work with the function without a fatal error, the function anova has its own way of “pretty” printing [to quote the help file] which is not compatible with the character vector in the P value column and thus will show a P value of 1. So forcing to a data frame is necessary. A minor modification is to ignore the NAs in the Residual row created by the data frame which would otherwise give an error.

The three decimal places for P values is coded into the function by default and can be changed by the dig option. For example, dig = 1 will give you \(<0.1\). You can then call your ANOVA table and the fixp function through knitr::kable() or your favourite HTML/LaTeX table formatter. e.g. kable(fixp(anova(lm(...))), digits = ...). If you don’t want to print NAs, it’s probably better to use the options in your chosen formatting function - e.g. the knitr.kable.NA option in kable.

Avatar
Jacinta Kong
Postdoctoral Fellow

My research interests include species distributions, phenology & climate adaptation of ectotherms.

Next
Previous

Related