user4768948
user4768948

Reputation: 11

Multilingual plots with ggplot

Sometimes it is necessary to create plots of a set of data in two or more languages. It is of course possible to manually type ggplot layers to make axis titles and guide legend labels publication-ready but I would like to add some automation to reduce the amount of code needed.

Instead of adding layers to replace e.g. variable names in the axis label, I would like to just wrap the ggplot call inside a function like replace_labels(plot,target_language) that would automatically look the strings up in a dictionary I have defined. I have written some code that almost works but the problem is that

I also considered replacing the strings in the data.frame but that is not a good solution because I would need to write the ggplot calls for each language which seems like unnecessary code replication to me. Any suggestions how to internationalize plots elegantly without needing to rewrite ggplot?

Edit: added a slightly modified example created by mdag02.

library(ggplot2)

language <- list(
  fr_FR = list(
    title = "Iris",
    subtitle = "Le jeu de données connu",
    caption = "French",
    x = "Longueur des sépales, cm",
    y = "Largeur des sépales, cm",
    labels = c(setosa = "Setosa", versicolor = "Versicolor", virginica = "Virginica"),
    legend = "Espèce",
    labeller = function(variable,value) c(setosa = "Setosa", versicolor = "Versicolor", virginica = "Virginica")[value]
  ),
  en_US = list(
    title = "Iris",
    subtitle = "The famous dataset",
    caption = "English",
    x = "Sepal Length, cm",
    y = "Sepal Width, cm",
    labels = c(setosa = "Setosa", versicolor = "Versicolor", virginica = "Virginica"),
    legend = "Species",
    labeller = function(variable,value) c(setosa = "Setosa", versicolor = "Versicolor", virginica = "Virginica")[value]
  )
)

for (l in names(language)) {
  message(l)
  current <- language[[l]]

  print(ggplot(data = subset(iris,
                             Species %in% c("virginica","versicolor")),
               aes(x = Sepal.Length,
                   y = Sepal.Width)) +
          geom_point() +
          facet_grid(~Species,labeller = current$labeller)+
          scale_colour_discrete(labels = current$labels,
                                name = current$legend) + 
          labs(
            title = current$title,
            subtitle = current$subtitle,
            caption = paste(current$caption, format(Sys.Date(), "%Y-%m-%d")),
            x = current$x,
            y = current$y))

  ggsave(file = paste0("iris_", l, ".png"), width = 21, height = 13, units = "cm", scale = 0.8)
}

I would like to make it so that I only need to write code up to the geom such as geom_point and let the computer handle the label replacement formatting, e.g. scale_colour_discrete like so:

ggplot(data = subset(iris,
                     Species %in% c("virginica","versicolor")),
                   aes(x = Sepal.Length,
                       y = Sepal.Width)) +
              geom_point() +
              facet_grid(~Species)

I could get in that direction by encapsulating the formatting layers in a variable like myformats but a drawback of this method is that if I want to manually change colors, then I need to re-introduce the label replacement code because my manual formatting will override the label replacements in the myformats variable.

Also, if I decide that I want to plot Petal.Width instead, then I need to remember to change the label in both dictionaries and the ggplot call. I'm terrible at remembering so I would again prefer to leave it to the computer.

Upvotes: 1

Views: 778

Answers (1)

mdag02
mdag02

Reputation: 1175

You could loop through a list of strings :

library(ggplot2)

language <- list(
    fr_FR = list(
            title = "Iris",
            subtitle = "Le jeu de données connu",
            caption = "French",
            x = "Longueur",
            y = "Largeur"
    ),
    en_US = list(
            title = "Iris",
            subtitle = "The famous dataset",
            caption = "English",
            x = "Length",
            y = "Width"
    )
)

for (l in names(language)) {
    message(l)
    current <- language[[l]]

    ggplot(data = iris, aes(Sepal.Length, Sepal.Width)) +
        geom_point() +
        geom_smooth() +
        labs(
            title = current$title,
            subtitle = current$subtitle,
            caption = paste(current$caption, format(Sys.Date(), "%Y-%m-%d")),
            x = current$x,
            y = current$y)

    ggsave(file = paste0("iris_", l, ".svg"), width = 21, height = 13, units = "cm", scale = 0.8)
}

Upvotes: 2

Related Questions