1

In ggplot, I often need to edit x axis labels. My normal routine is to create an additional named vector for labels (e.g., my_labels), then use scale_x_labels(labels = my_labels).

Especially, this method is useful when needing to translate the labels to a different language. However, this works incorrectly when trying to wrap labels text in a Right-to-Left language.

Example

1 -- a simple bar plot

library(dplyr)
library(ggplot2)

mpg %>%
  filter(class == 'pickup' | class == "suv" | class == "compact") %>%
  ggplot(aes(class, fill = factor(class))) +
  geom_bar()

just_mpg_barplot

2 -- create a vector that translates x axis labels from English to Hebrew

my_labels <-
  c(
    pickup = "פיקאפ",
    suv = "סיובי",
    compact = "קומפקטי"
  )

3 -- recreate bar plot, now with new Hebrew labels

mpg %>%
  filter(class == 'pickup' | class == "suv" | class == "compact") %>%
  ggplot(aes(class, fill = factor(class))) +
  geom_bar() +
  scale_x_discrete(labels = my_labels)  # <------ this is the addition, and it works as intended

with_hebrew_labels_still_ok


4 -- Problem here: I want to add text wrapping function for the labels text, but it screws up the order

To keep it simple, I chose short Hebrew labels that don't meet wrapping criteria, but still demonstrate the fundamental problem.

library(stringr)

mpg %>%
  filter(class == 'pickup' | class == "suv" | class == "compact") %>%
  ggplot(aes(class, fill = factor(class))) +
  geom_bar() +
  scale_x_discrete(labels = str_wrap(my_labels, 10)) ## based on: https://stackoverflow.com/a/21894897/6105259

problem_when_wrapping
As can be seen, merely adding stringr::str_wrap() messed up the order of labels. This problem repeats with other wrapping techniques (this one too, for example).

Any idea how I could specify external named vector for x axis labeling, and apply a text wrapping method in an RTL language (e.g., Hebrew) while preserving the correct order?

Emman
  • 1,295
  • 8
  • 19

1 Answers1

2

For some reason I also don't understand, str_wrap() unnames the output, so you can't rely on the named matching anymore. Here are two solutions:

library(tidyverse)
library(stringr)

my_labels <-
  c(
    pickup = "פיקאפ",
    suv = "סיובי",
    compact = "קומפקטי"
  )

mpg %>%
  filter(class == 'pickup' | class == "suv" | class == "compact") %>%
  ggplot(aes(class, fill = factor(class))) +
  geom_bar() +
  scale_x_discrete(labels = vapply(my_labels, str_wrap, character(1), width = 10))


mpg %>%
  filter(class == 'pickup' | class == "suv" | class == "compact") %>%
  ggplot(aes(class, fill = factor(class))) +
  geom_bar() +
  scale_x_discrete(labels = setNames(str_wrap(my_labels, 10), names(my_labels)))

Also note that this is not an RTL language issue:

my_labels <-
  c(
    pickup = "Pickup",
    suv = "SUV",
    compact = "Compact"
  )

mpg %>%
  filter(class == 'pickup' | class == "suv" | class == "compact") %>%
  ggplot(aes(class, fill = factor(class))) +
  geom_bar() +
  scale_x_discrete(labels = str_wrap(my_labels, 10))

Also mislabels the x-axis.

teunbrand
  • 17,545
  • 3
  • 14
  • 30