plot_trait_space(pca_scores, groups, axes)

Publication-ready functional space plot: PCA scores coloured by group, with density contours and species labels.

ggplot2functional space
Args:pca_scores — data.frame with PC1,PC2groups — grouping vectoraxes=c(1,2)
plot_trait_space <- function(pca_scores, groups = NULL, axes = c(1, 2),
                            alpha = 0.6, contour = TRUE,
                            label_col = NULL) {
  library(ggplot2)
  df <- as.data.frame(pca_scores)
  xc <- paste0("PC", axes[1]); yc <- paste0("PC", axes[2])
  
  p <- ggplot(df, aes(.data[[xc]], .data[[yc]]))
  
  if (!is.null(groups)) {
    df$group <- groups
    p <- ggplot(df, aes(.data[[xc]], .data[[yc]], colour = group, fill = group))
    if (contour)
      p <- p + stat_ellipse(geom = "polygon", alpha = 0.08, linewidth = 0.4)
    p <- p + geom_point(alpha = alpha, size = 2)
  } else {
    p <- p + geom_point(alpha = alpha, size = 2, colour = "#2471a3")
    if (contour)
      p <- p + stat_density_2d(colour = "#2471a3", alpha = 0.4)
  }
  
  if (!is.null(label_col))
    p <- p + ggrepel::geom_text_repel(aes(label = .data[[label_col]]),
                                      size = 2.5, max.overlaps = 15)
  
  p + labs(x = xc, y = yc) + theme_bw() +
    theme(panel.grid.minor = element_blank(),
          legend.title = element_blank())
}