Saving ggplot with expression and unicode in axis title with cairo
Asked Answered
M

2

6

I'd like to save the following plot:

library(ggplot2)

myplot <- ggplot(iris) +
  geom_point(aes(x = Sepal.Width, y = Sepal.Length)) +
  ylab(expression(~delta^13*C~"[\211]"))

ggsave(myplot, 
       filename = "myplot.png", 
       type = "cairo")

But I get the following error:

Error in grid.Call.graphics(C_text, as.graphicsAnnot(x$label), x$x, x$y,  : 
  Metric information not available for this family/device

The problem must be the combination of expression and unicode, as those two work:

myplot <- ggplot(iris) +
  geom_point(aes(x = Sepal.Width, y = Sepal.Length)) +
  ylab("[\211]")

myplot <- ggplot(iris) +
  geom_point(aes(x = Sepal.Width, y = Sepal.Length)) +
  ylab(expression(~delta^13*C))

How can I solve this problem?

Edit: I'd like to print the "per mille"-symbol. Apparently its unicode is U2030 and I had mistakenly assumed that "\211" would be a unicode, but must be something else.

Edit 2: In the meantime, I found this question with a similar problem. There, a suggestion is to save the plot with encoding = "MacRoman", which unfortuantely does not work for me:

Error in png_dev(..., res = dpi, units = "in") : 
  unused argument (encoding = "MacRoman")

Edit 3:

> capabilities()["cairo"]
cairo 
 TRUE 
> sessionInfo()
R version 4.0.1 (2020-06-06)
Platform: x86_64-w64-mingw32/x64 (64-bit)
Running under: Windows 7 x64 (build 7601) Service Pack 1

Matrix products: default

locale:
[1] LC_COLLATE=German_Germany.1252  LC_CTYPE=German_Germany.1252    LC_MONETARY=German_Germany.1252 LC_NUMERIC=C                   
[5] LC_TIME=German_Germany.1252    

attached base packages:
[1] stats     graphics  grDevices utils     datasets  methods   base     

other attached packages:
[1] patchwork_1.1.1 ggplot2_3.3.5   dplyr_1.0.7  
Mahau answered 1/10, 2021 at 14:42 Comment(4)
Have you tried with \u211 or \u0211? That's the way I would add unicode symbols. And at least on my machine this works without any error.Excavator
@Excavator Hm, when I try, [<U+0211>] is printed as the axis label. Any idea what I am doing wrong?Mahau
"[\u211]" works for me too. What font are you using?Practical
@RobinGertenbach the default setting (Arial, I think?). But I doubt it's a font problem as it works on its own, it's just the combination with expression that doesn't.Mahau
A
3

Which unicode symbol are you trying to actually use. I guess it is only your syntax for specifying the unicode symbol that is wrong.

Try this code:

myplot <- ggplot(iris) +
  geom_point(aes(x = Sepal.Width, y = Sepal.Length)) +
  ylab(expression(~delta^13*C~"\U0211"))

ggsave(myplot, 
       filename = "myplot.png", 
       type = "cairo")

This works perfectly for me.

Gives a plot that looks like this: enter image description here

You use "\U0211". So "\U for specifying you want unicode and then the code.

Look here for the unicode symbols: https://en.wikipedia.org/wiki/List_of_Unicode_characters

It's the first column you have to input to get the right symbol. So e.g. for U+020F you write "\U020F"

Update

Here an example with the new information about your unicode symbol

myplot <- ggplot(iris) +
  geom_point(aes(x = Sepal.Width, y = Sepal.Length)) +
  ylab(expression(~delta^13*C~"\U2030"))

 ggsave(myplot, 
           filename = "myplot.png", 
           type = "cairo")

Gives me this plot:

enter image description here

Would you mind trying the exact code above? Also try to run without saving - since the saving of the plot actually shouldn't be the issue.

So also try to just run

library("ggplot2")
ggplot(iris) +
      geom_point(aes(x = Sepal.Width, y = Sepal.Length)) +
      ylab(expression(~delta^13*C~"\U2030"))

There, take a look if the y-axis label is displayed correctly.

If it still does not work:

It might also be, that the font you are using does not contain the unicode char you are trying to use.

Then add the following to your plot code:

ggplot(iris) +
  geom_point(aes(x = Sepal.Width, y = Sepal.Length)) +
  ylab(expression(~delta^13*C~"\U2030")) +
  theme(text=element_text(family="Arial Unicode MS"))

The "Arial Unicode MS" can actually be any font that is available and includes the unicode char in the form that you want it.

Maybe these hints already solve the problem - if not just write another comment, maybe you additionally need some further steps.

Further steps:

Since it still did not work and you mention it seems to be specific to saving with type = cairo try the following:

First provide some more info and check for cairo with this command:

capabilities()["cairo"]

Result should be true.

Then post us some information about your system

sessionInfo()

As these font and plotting things are often dependent on your OS.

Then we make 100% sure, that we have the fonts/unicode symbols available:

library(ggplot2)
install.packages("extrafont")
library("extrafont")
font_import()
loadfonts()
fonts()

The call to fonts() should now gibe output, which fonts are available.

Maybe you can post these infos additionally, that we can give you further steps.

Afterwards you can try again, using extrafonts() alone sometimes already solves the problem:

library("ggplot2")
library("extrafont")
font_import()
loadfonts()

myplot <- ggplot(iris) +
  geom_point(aes(x = Sepal.Width, y = Sepal.Length)) +
  ylab(expression(~delta^13*C~"\U2030")) +
  theme(text=element_text(family="Arial Unicode MS"))
  
ggsave(myplot, 
       filename = "myplot.png", 
       type = "cairo")

As I said capabilities()["cairo"] must have returned true and family="Arial Unicode MS" must be some font that fonts() returned

Also worth trying a different grDevice after getting extrafont ready

library("extrafont")
font_import()
loadfonts()

myplot <- ggplot(iris) +
  geom_point(aes(x = Sepal.Width, y = Sepal.Length)) +
  ylab(expression(~delta^13*C~"\U2030")) +
  theme(text=element_text(family="Arial Unicode MS"))
  
ggsave(myplot, 
       filename = "myplot.png", 
       type = "cairo-png")

There are also more you can try ... here is a very interesting article about saving graphics on different OS. Interestingly depending on your OS and graphic device exported figures look slightly different.

Just read in your comment you want to use Cairo to increase the quality. Try if it works with ragg instead of Cairo - the quality might be even better.

ragg provides a set of high quality and high performance raster devices, capable of producing png, tiff, or ppm files, or a matrix of raw color values directly within R.

ragg is part of our broader effort to improve graphics performance and quality in R at all levels of the stack

library(ragg)

myplot <- ggplot(iris) +
  geom_point(aes(x = Sepal.Width, y = Sepal.Length)) +
  ylab(expression(~delta^13*C~"\U2030")) +
  theme(text=element_text(family="Arial Unicode MS"))

ggsave(
       filename = "myplot3.png",
       myplot,
       device = ragg::agg_png( 
         width = 3000,
         height = 3000, 
         units = "px",
         res = 500)
)

Since you still had now some issues with expression, you can also combine this also with ggtext. Then there is no need for expression.

myplot <- ggplot(iris) +
  geom_point(aes(x = Sepal.Width, y = Sepal.Length)) +
  ylab("\U03B4<sup>13</sup>C\U2030") +
  theme(
    axis.title.y = element_markdown(size = 11, lineheight = 1.2)
  )

ggsave(
       filename = "myplot4.png",
       myplot,
       device = ragg::agg_png( 
         width = 3000,
         height = 3000, 
         units = "px",
         res = 500)
)

Using the package ggtext basically enables you to do all kind of things with your axis title (bold, multiple colors, different sizes, ... all in one label). See also ggtext manual.

Adversary answered 4/10, 2021 at 10:52 Comment(10)
Hard to tell at the moment, try the updated code example from the answer and maybe we know a little bit more afterwards :)Adversary
Thanks, but I was able to display the plot just fine from the beginning. The error only occurrs when I try to save it WITH type = cairo. Saving without does type = cairo work though. So the problem must be the combination of that particular symbol AND type = cairo, I guess. Changing the font doesn't solve that, unfortunately.Mahau
Can you provide the output mentioned in the bottom of my answer? Makes it easier to provide help in the right direction. (sessionInfo(), capabilities()["cairo"] and fonts() )Adversary
I've added the output of the first two to my question. font_import() does not work for me: Scanning ttf files in C:\Windows\Fonts ... Extracting .afm files from .ttf files... C:\Windows\Fonts\AGENCYB.TTF : No FontName. Skipping. .. same for all fonts..Mahau
Use this workaround to (hopefully) fix this problem and then try again: https://mcmap.net/q/363350/-how-can-i-resolve-the-quot-no-font-name-quot-issue-when-importing-fonts-into-r-using-extrafontAdversary
Another question: If it works without type = cairo. Is there actually a reason why you need exactly type = cairo?Adversary
Thanks, that worked. Arial Unicode MS is available, but it is still not working. Changing to cairo-png returns the same error. I'd like to use cairo to improve the quality.Mahau
Try if it works with ragg (see updated answer) - could possibly provide even better quality.Adversary
Thanks, with ragg the per mille symbol gets displayed perfectly but the delta is displayed as a rectangle (in the saved plot only).. :SMahau
Oh seems to have issues with the expression now. Try using the ggtext solution I wrote you down. ggtext is anyway amazing, since it enables you to format the axis title in so many different ways (colors, size, even images..).Adversary
D
1

Certain unicodes only work with certain fonts. Here is a list of fonts that work with unicode u2030.

The package emojifont makes it easier to use certain unicodes, by rendering the font/family you need to make it possible to save your file. That way you skip having to find the correct font and installing it in your OS.

library(ggplot2)
install.packages('emojifont')
library(emojifont)



myplot <- ggplot(iris) +
  geom_point(aes(x = Sepal.Width, y = Sepal.Length)) +
  ylab(expression(~delta^13*C~"[\u2030]"))


myplot

ggsave(my_plot, 
       filename = "myplot.png", 
       type = "cairo")

It also works with \u211.

Daegal answered 8/10, 2021 at 13:44 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.