3

I need to change the family and size of a specific x-axis element of a barplot, based on a condition.

I can successfully modify face using:

library(ggplot2)
ggplot(iris, aes(Species, Petal.Length)) + 
  geom_boxplot() + 
  coord_flip() +
  theme(axis.text.y = element_text(face = ifelse(levels(iris$Species)=="setosa","bold","italic")))

As suggested by: https://stackoverflow.com/a/20609878/8534926

However, for some reason when I try to apply family and size an empty gap is created between the axis and names.

ggplot(iris, aes(Species, Petal.Length)) + 
  geom_boxplot() + coord_flip() + 
  theme(axis.text.y = element_text(family = ifelse(levels(iris$Species)=="setosa","sans","mono")))

or

ggplot(iris, aes(Species, Petal.Length)) + 
  geom_boxplot() + coord_flip() + 
  theme(axis.text.y = element_text(size = ifelse(levels(iris$Species)=="setosa", 10, 20)))

I try to edit it using margin, but overlays can occur when the names are modified (using shiny app, for example).

what is this gap? Can I delete it?

  • interesting. possibly somehow related: https://stackoverflow.com/questions/53159879/ggplot2-axis-text-margin-with-modified-scale-position. – tjebo Jan 15 '20 at 20:56
  • I think this is a bug and I have [raised a Github issue](https://github.com/tidyverse/ggplot2/issues/3739). I am curious for their answers. I generally think 'less is more' and you may want to consider a different way of highlighting specific subsets of your data. E.g., if the data points get different shape/ grey value/ color (if really it needs to be color), then there should be no need to change the font or size of one x category... – tjebo Jan 16 '20 at 09:23
  • @Tjebo Thanks for your comment. I'm using color as a highlight, but I would like to use every possible highlight and I need to use specific fonts. – Vander Souza Jan 16 '20 at 14:34

2 Answers2

2

The problem is fixed in the upcoming ggplot2 3.3.0, but it now triggers a warning, because this approach of formatting axis text is not reliable and could stop working at any point in the future.

library(ggplot2) # v 3.3.0 or higher

# discouraged, triggers warning message
ggplot(iris, aes(Species, Petal.Length)) + 
  geom_boxplot() + coord_flip() + 
  theme(
    axis.text.y = element_text(
      size = ifelse(levels(iris$Species)=="setosa", 10, 20)
    )
  )
#> Warning: Vectorized input to `element_text()` is not officially supported.
#> Results may be unexpected or may change in future versions of ggplot2.

As an alternative, the ggtext package under development attempts to provide a principle approach to this problem, by encoding the formatting instructions into the text labels.

library(ggtext) # remotes::install_github("clauswilke/ggtext")
library(dplyr)
#> 
#> Attaching package: 'dplyr'
#> The following objects are masked from 'package:stats':
#> 
#>     filter, lag
#> The following objects are masked from 'package:base':
#> 
#>     intersect, setdiff, setequal, union
library(glue)
#> 
#> Attaching package: 'glue'
#> The following object is masked from 'package:dplyr':
#> 
#>     collapse

iris %>%
  mutate(
    Species = ifelse(
      Species == "setosa",
      "<span style = 'font-size:10pt'>setosa</span>",
      glue("<span style = 'font-size:20pt'>{Species}</span>")
    )
  ) %>%
  ggplot(aes(Species, Petal.Length)) + 
  geom_boxplot() + coord_flip() + 
  theme(axis.text.y = element_markdown())

Created on 2020-01-16 by the reprex package (v0.3.0)

Claus Wilke
  • 16,992
  • 7
  • 53
  • 104
  • thank you. I'm trying to test your code (ggtext), but the following error is occurring: `Error in (angle %||% 0)%%360 : non-numeric argument to binary operator` – Vander Souza Jan 16 '20 at 17:01
  • Please file an issue [here](https://github.com/clauswilke/ggtext/issues) and make sure to provide a reproducible example. – Claus Wilke Jan 16 '20 at 22:06
1

I don't have any idea why this happens. Very peculiar. But you can change this margin with margin.
However, you need to specify the unit, e.g. as 'inch'. It is then a matter of trial and error to find the right values, this will also hugely depend on your final plot output.
Maybe it would be safer and easier to find different ways of highlighting your data?

library(ggplot2)

ggplot(iris, aes(Species, Petal.Length)) + 
  geom_boxplot() + 
  theme(axis.text.y = element_text(family =  
          ifelse(levels(iris$Species)=="setosa","sans","mono"),
        margin = margin(r = -2, l = 0.8, unit = 'in'))) +
  coord_flip()

Created on 2020-01-15 by the reprex package (v0.3.0)

tjebo
  • 21,977
  • 7
  • 58
  • 94
  • 1
    The negative margin is undoing the effect of a bug in ggplot2. This example will stop working in a few weeks, when the next ggplot2 is released. – Claus Wilke Jan 16 '20 at 14:45