0

I have a plot where the bottom tick has a label of 'mean'. I want this to be in italics, but its not working. Any ideas?

I get the error:Vectorized input to element_text() is not officially supported. ℹ Results may be unexpected or may change in future versions of ggplot2.

However, even if I change the code to:

....theme(axis.text.y=element_text(face='italic')....

nothing happens either and all labels on the y axis stay 'plain'. The vector form works for the colour so I don't understand why face isn't working.

example code

stacked <- ggplot(tally, aes(fill=Ellenberg, y=n, x=Quadrat)) +
    geom_bar(position='stack', stat='identity', show.legend=FALSE) +
    scale_x_discrete(labels=labels) +
    scale_fill_manual(values = colLegend) +
    theme_classic() +
    facet_wrap(~ Q, nrow=1, scales='free_x') +
    expand_limits(y=-3) +
    geom_text(
      label=tally$values, y=-3, color='red', fontface='italic', size=4.5, family="Calibri") +
    labs(x='Year', 
         y='    Number of Plants\n\n',
         title=plotTitles[[j]],
         subtitle = plotSubTitles[[j]]) +
    scale_y_continuous(breaks = c(-3, 0, 5, 10, 15, 20, 25),
                       labels=expression("Mean", "0", "5", "10", "15", "20", "25")) +
    theme(axis.text.y=element_text(face=c("italic", "plain", "plain", "plain", "plain", "plain", "plain"), 
                                   colour=c('red','black','black','black','black','black','black'))) +
    theme(axis.ticks=element_line(colour=c('white','black','black','black','black','black','black'))) + 
    theme(plot.title = element_text(size=20, face="bold", family="Calibri"),
        plot.subtitle = element_text(size=20, family="Calibri")) +
    theme(text=element_text(size=20, family="Calibri")) +
    theme(axis.title.y=element_text(margin=margin(l=20)))
  
  plot(stacked)
  plotList[[dfName]] <- stacked
  
  j = j + 1

Example Plot

enter image description here

Melanie Baker
  • 449
  • 1
  • 13
  • related https://stackoverflow.com/questions/39282293/using-italics-and-non-italics-in-the-same-category-label – tjebo Apr 03 '23 at 17:52

2 Answers2

2

The issue is that you wrapped you labels in expression. Dropping that should give you your desired result but you will still get the warning about Vectorized input is not officially supported:

Using a minimal reproducible example based on mtcars:

library(ggplot2)

ggplot(mtcars, aes(hp, mpg)) +
  geom_point() +
  scale_y_continuous(
    breaks = c(-3, 0, 5, 10, 15, 20, 25),
    labels = c("Mean", "0", "5", "10", "15", "20", "25"),
    limits = c(-3, NA)
  ) +
  theme(axis.text.y = element_text(
    face = c("italic", rep("plain", 6)),
    colour = c("red", rep("black", 6))
  ))
#> Warning: Vectorized input to `element_text()` is not officially supported.
#> ℹ Results may be unexpected or may change in future versions of ggplot2.

stefan
  • 90,330
  • 6
  • 25
  • 51
2

This is maybe better done with the {ggtext} package. Plain italics are super easy with simple markdown formatting (plot 1), but if you want to use a different color, you will need some CSS formatting (plot 2) - ggtext has some limited support for CSS.

However, if I may make a suggestion. You're quite awkwardly combining a continuous axis with a categorical variable, which is actually an aggregate measure. I think the neatest way forward would be to create two plots and combine them with for example patchwork (plot 3). This might seem more verbose, but it will be less bug prone in the long run.

Another option, maybe my preferred, would be to do add your aggregating row as a custom annotation outside the plot panel (plot 4).

library(ggplot2)
df <- data.frame(
  q = rep(paste0("Q", 1:9), each = 3),
  Year = rep(c(19, 20, 22), 9),
  n_plant = rnorm(27, 20),
  mean = sample(c(.1, .2), 27, rep = T)
)

p <- ggplot(df, aes(Year, n_plant)) +
  geom_col() +
  geom_text(aes(y = -5, label = mean)) +
  facet_wrap(~q, ncol = 9)

Just italics are very simple.

p + scale_y_continuous(
  breaks = seq(-5, 20, 5),
  labels = c("*mean*", seq(0, 20, 5))
) +
  theme(axis.text.y = ggtext::element_markdown())

If you want to color differently, you will need some basic CSS formatting.


p + scale_y_continuous(
  breaks = seq(-5, 20, 5),
  labels = c("<i><span style = 'color:red;'>mean</span></i>", seq(0, 20, 5))
) +
  theme(axis.text.y = ggtext::element_markdown())

My suggestion to create those plots separately.

library(patchwork)

p <- ggplot(df, aes(Year, n_plant)) +
  geom_col() +
  facet_wrap(~q, ncol = 9)

p_ann <-
  ggplot(df, aes(Year, n_plant)) +
  geom_text(aes(y = "mean", label = mean), color = "red",
            size = 6*5/14) +
  facet_wrap(~q, ncol = 9) +
  ## this is the default expansion with bar graphs, you need this for alignment
  scale_x_continuous(expand = c(0, 0.6)) +
  theme_void() +
  theme(axis.text.y = element_text(color = "red", face = "italic", size = 10), 
        strip.text = element_blank())

p/p_ann +
  plot_layout(heights = c(1, .1))

Or, annotate outside the plot area

## make data frame for your single facet annotation
annot_df <- data.frame(Year = 18, n_plant = -5, q = "Q1", label = "mean")

ggplot(df, aes(Year, n_plant)) +
  geom_col() +
  facet_wrap(~q, ncol = 9) +
## now the mean bit
  geom_text(data = annot_df, aes(label = label), fontface = "italic", color = "red", hjust = 1) +
  geom_text(aes(y = -5, label = mean), color = "red", size = 6*5/14) +
  coord_cartesian(xlim = range(df$Year), ylim = c(0, max(df$n_plant)), clip = "off") +
## add plot margins
  theme(plot.margin = margin(b = 1, l = 1, unit = "in"))

enter image description here

tjebo
  • 21,977
  • 7
  • 58
  • 94