rggplot2dplyrflextable

Conflict between flextable, ggplot2, and Arabic & Hindi


I'm having trouble getting ggplot2 to work with Arabic and Hindi when flextable is loaded.

Here's a first run that also includes English and Russian to demonstrate that everything works without flextable loaded:

library(dplyr) # data management
#library(flextable) # used elsewhere in application
library(ggplot2) # chart

datDf <- tibble(En = c("Orange","Purple"),
                Ru = c("оранжевый","Пурпурный"),
                Hi = c("नारंगी","जामुनी"),
                Ar = c("برتقالي","بنفسجي"), # R handles the direction change
                xMin = c(1,2),
                xMax = c(3,4)) %>%
  # keep rows in order for plot
  mutate(across(c(En,Ru,Hi,Ar), ~factor(.x, levels=rev(.x)))) 

plotFun <- function(labLang){
  # x-axis labels
  xTiks <- switch(deparse(substitute(labLang)),
                  En = c("1.0\nAlmost Never",
                         "2.0\nRarely",
                         "3.0\nSometimes",
                         "4.0\nOften",
                         "5.0\nAlmost Always"),
                  Ru = c("1.0\nПочти никогда",
                         "2.0\nРедко",
                         "3.0\nИногда",
                         "4.0\nЧасто",
                         "5.0\nПочти всегда"),
                  Hi = c("1.0\nलगभग कभी नही",
                         "2.0\nशायद ही कभी",
                         "3.0\nकभी-कभी",
                         "4.0\nअक्सर",
                         "5.0\nलगभग हमेशा"),
                  Ar = c("1.0\nتقريبًا لا على الإطلاق",
                         "2.0\nنادرًا",
                         "3.0\nفي بعض الأحيان",
                         "4.0\nغالبًا",
                         "5.0\nتقريبًا دائمًا")
                  )
  plt1 <- ggplot(datDf, aes(y={{labLang}}, xmin=xMin, xmax=xMax)) +
    geom_linerange()
  plt2 <- if (deparse(substitute(labLang)) == "Ar") {
    # handle right-to-left for Arabic
    plt1 +
      scale_x_reverse(labels=xTiks, limits=c(5,1)) +
      scale_y_discrete(position="right")
  } else {
    plt1 +
      scale_x_continuous(labels=xTiks, limits=c(1,5))
  }
  return(plt2)
}

plotFun(En) # English
plotFun(Ru) # Russian
plotFun(Hi) # Hindi
plotFun(Ar) # Arabic

Plot outputs run as expected:

Line range plot with English labels Line range plot with Russian labels Line range plot with Hindi labels Line range plot with Arabic labels

Here's the tricky part. If I remove the # from library(flextable) and re-run everything in the same session, it all still works. If I then restart the session and re-run everything, the English and Russian plots are still fine, but the Hindi plot is missing the labels, and the Arabic plot won't render at all:

Line range plot missing Hindi labels

The problem persists even if I unload flextable and all of its dependencies before running the plot function:

unloadNamespace("flextable")
unloadNamespace("data.table")
unloadNamespace("gdtools")
unloadNamespace("Rcpp") # unload gdtools first
unloadNamespace("fontquiver") # unload gdtools first
unloadNamespace("fontLiberation") # unload fontquiver first
unloadNamespace("fontBitstreamVera") # unload fontquiver first
unloadNamespace("officer")
unloadNamespace("openssl") # unload officer first
unloadNamespace("askpass") # unload openssl first
unloadNamespace("uuid") # unload officer first
unloadNamespace("xml2") # unload officer first
unloadNamespace("zip") # unload officer first
unloadNamespace("ragg") # unload officer first
unloadNamespace("textshaping")
unloadNamespace("systemfonts") # unload gdtools, ragg, textshaping first

As far as I can tell, unloading all of those didn't remove anything that comes with dplyr, ggplot2, and whatever is there by default.

The problem isn't with things only working with the Latin alphabet because it still works with Russian, and the problem isn't with right-to-left languages because Hindi doesn't work either.


Solution

  • Thanks to @yuk's comments, I was able to narrow the problem down to the textshaping package (a dependent of ragg, which is a dependent of officer, which is a dependent of flextable). Upon a closer reading of this thread (How to unload a package without restarting R), I realized that unloadNamespace wasn't doing everything I needed. Instead, plugging in pkgload::unload("textshaping") before the plot functions solved the issue. Including library(textshaping) after I've rendered the charts puts it back in place just fine for when I need it later.