1

I would like to add a p-value to a scatter-plot, while respecting APA style. This entails two elements: (a) an italicized p, and (b) stripping the leading zero (but also: formatting values smaller than .001 as < .001).

We can strip the leading zero with a custom formula

# Formatting formula
format.p <- function(p, precision = 0.001) {
  digits <- -log(precision, base = 10)
  p <- formatC(p, format = 'f', digits = digits)
  p[p == formatC(0, format = 'f', digits = digits)] <- paste0('< ', precision)
  sub("0", "", p)}

# Get p-value
(p = cor.test(mtcars$wt, mtcars$mpg)$p.value)
1.293959e-10

# Format p-value
(p = format.p(p))
"< .001"

# Make plot    
library(ggplot2)
ggplot(mtcars,aes(x=wt,y=mpg)) +
  stat_smooth(geom="line",method="lm")+
  annotate(geom="text",label=paste0("p = ", p),x=4.5,y=25,size=8)

enter image description here

We can also achieve the italicized p like this:

ggplot(mtcars,aes(x=wt,y=mpg)) +
  stat_smooth(geom="line",method="lm") +
geom="text",label=paste0("italic('p')~'='",p),parse=T,x=4.5,y=25,size=8)

enter image description here

But notice then that we lost the stripped zero (the leading zero is back while we don't want it). Any idea how to fix this?

rempsyc
  • 785
  • 5
  • 24
  • 1
    you could try `label=sprintf("italic('p')~'%s'", p)` – rawr Feb 20 '21 at 20:11
  • It almost works! (Italic *p* while preserving zero strip). Except now we are missing the equal sign. How would you fit it in there? – rempsyc Feb 20 '21 at 20:51
  • 1
    you can add any additional text in the string but it doesnt make sense to me to have `p = <.001`, it's either `p = .001` or `p < .001` – rawr Feb 20 '21 at 21:03
  • Oh ok I see! I was afraid that the `=` sign would be wrongly italicized as well somehow, but this is not the case so all is good! I guess you are right that it makes less sense in the case of `< .001`, but often the *p* value will be exact (great than `.001`) so in this case we will want the equal sign. – rempsyc Feb 20 '21 at 21:31
  • Do you want to add the solution as answer? (Or would you prefer I do?) – rempsyc Feb 20 '21 at 21:31
  • @rawr Ok I found a solution for the equal sign! We simply had to modify the `format.p()` function to accommodate a conditional sign right there. `format.p <- function(p, precision = 0.001) { digits <- -log(precision, base = 10) p <- formatC(p, format = 'f', digits = digits) if (p < .001) { p = paste0('< ', precision)} if (p >= .001) { p = paste0('= ', p) } sub("0", "", p) }` – rempsyc Feb 20 '21 at 23:11

1 Answers1

2

Solution provided by @rawr in comments (thank you!)

The key was to change label=paste0("italic('p')~'='", p) to label=sprintf("italic('p')~'%s'", p).

Furthermore, in order to avoid having situations where the function would simultaneously output equal and smaller than signs (e.g., p = < .001), I have also modified the format.p() function to choose either < or = depending on the situation.

Here's the final solution:

# Formatting formula
format.p <- function(p, precision = 0.001) {
  digits <- -log(precision, base = 10)
  p <- formatC(p, format = 'f', digits = digits)
  if (p < .001) {
    p = paste0('< ', precision)}
  if (p >= .001) {
    p = paste0('= ', p)    }
  sub("0", "", p)
}

# Get p-value
(p = cor.test(mtcars$wt, mtcars$mpg)$p.value)
1.293959e-10

# Format p-value
(p = format.p(p))
"< .001"

# Make plot    
library(ggplot2)
ggplot(mtcars,aes(x=wt,y=mpg)) +
  stat_smooth(geom="line",method="lm")+
  annotate(geom="text",label=sprintf("italic('p')~'%s'",p),parse=TRUE,x=4.5,y=25,size=8)

enter image description here

rempsyc
  • 785
  • 5
  • 24