Search code examples
rggplot2vegan

Annotate in ggplot2 does not honor newline is a pasted and parsed command


Question

How do I get paste and parse in annotate of ggplot2 to honor a newline (\n) character?

Problem and MWE

I am trying to reproduce in ggplot2 a stressplot of an NMDS analysis using metaMDS in package vegan. Here is my MWE, followed by the resulting graph.

library(ggplot2)
library(tibble)
library(vegan)

set.seed(42) # for reproducibility

data(dune)
fit <- metaMDS(dune)
tib <- tibble(fit$diss, fit$dist, fit$dhat)
colnames(tib) <- c("diss", "dist", "dhat")
stress <- fit$stress
coord_x <- min(tib$diss)
coord_y <- max(tib$dist)
nonmetric_r2 <- round(1 - stress * stress, digits = 3)
linear_r2 <- round(summary(lm(fit$dist~fit$dhat))$adj.r.squared, 3)

## How do I get the newline character to be honored?
nonmetric_label = paste0("Non-metric~fit~italic(R)^2 ==", nonmetric_r2, "~\n Linear~fit~italic(R)^2 ==", linear_r2)

ggplot(tib,
       aes(x = diss, y = dist)) +
  geom_point(color = "blue") +
  geom_line(aes(x = diss, y = dhat), color = "red") +
  annotate(
    geom = "text",
    x = coord_x,
    y = coord_y,
    hjust = 0,
    #vjust = 1,
    label = nonmetric_label, parse = TRUE) +
  labs(x = "Observed Dissimilarity",
       y = "Ordination Distance")

enter image description here

The single annotated line above should be on two separate lines, as shown below (from stressplot(fit)).

Stressplot produced using vegan's stressplot function.

The offending line is

nonmetric_label = paste0("Non-metric~fit~italic(R)^2 ==", nonmetric_r2, "~\n Linear~fit~italic(R)^2 ==", linear_r2)

If I do not include the tilde before \n, then everything after the newline character disappears. I have tried various combinations of tilde placement and placing '\n~Linear~fit' in additional single quotes and back-ticks.

How do I get the desired annotation to appear on two lines?


Solution

  • One approach would be to use a vector of strings as a label and a vector of coordinates which will mach the desired annotation:

    nonmetric_label = c(paste0("Non-metric~fit~italic(R)^2 ==", nonmetric_r2),
                        paste0("Linear~fit~italic(R)^2 ==", linear_r2)) 
    
    ggplot(tib,
           aes(x = diss, y = dist)) +
      geom_point(color = "blue") +
      geom_step(aes(x = diss, y = dhat), color = "red", direction = "vh") +
      annotate(
        geom = "text",
        x = coord_x,
        y = c(coord_y, 0.95*coord_y),
        hjust = 0,
        #vjust = 1,
        label = nonmetric_label, parse = TRUE) +
      labs(x = "Observed Dissimilarity",
           y = "Ordination Distance")
    

    enter image description here

    As per suggestion of Jari Oksanen I have changed geom_line to geom_step. To match the output of stressplot(fit) an additional argument direction = "vh" is needed.