Saving ggplot with expression and unicode in axis title with cairo - r

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

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:
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:
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.

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.

Related

ggrepel::geom_text_repel not working in large mode/Rstudio notebook output (nor with cowplot)

I was wondering if anyone knew why this is happening. Here is a quick example of the code and screenshots.
library(ggplot2)
iris$randomratio <- iris$Sepal.Length/iris$Sepal.Width
plot_iris <- ggplot(iris, aes(x=Sepal.Length, y=Sepal.Width, color = Species)) +
geom_point() +
theme_light() +
ggrepel::geom_text_repel(data=subset(iris, randomratio > 2.7),
aes(Sepal.Length, Sepal.Width, label= Species))
plot_iris
cowplot::plot_grid(plot_iris, plot_iris, label = c('A', 'B'))
Now when I do this in an RMD file I get the points labelled that I want (right) But when I try to do this in the Rstudio notebook output I get the following:
NB It doesn't work with ggplot or cowplot. With cowplot it doesn't work in the regular file as well.
Does anyone know how I can fix this?
I see a warning with 'cowplot', but a figure with text labels.
Warning message:
In as_grob.default(plot) :
Cannot convert object of class character into a grob.
I see no warning with 'patchwork'. You need to be aware that with geom_text() if want to avoid text overlapping the points, instead of sub-setting the data you have to set labels to "". Reducing the size of the labels helps with the repulsion. Collecting identical legends when composing the plot gives also a bit more room. The code below renders well to a HTML notebook under R 4.1.0 and latest versions of the packages.
library(ggplot2)
library(patchwork)
iris$randomratio <- iris$Sepal.Length/iris$Sepal.Width
iris$label <- ifelse(iris$randomratio > 2.7, as.character(iris$Species), "")
plot_iris <-
ggplot(iris, aes(x=Sepal.Length, y=Sepal.Width, color = Species)) +
geom_point() +
theme_light() +
ggrepel::geom_text_repel(aes(label = label), size = 3, min.segment.length = 0)
plot_iris + plot_iris +
plot_annotation(tag_levels = 'A') +
plot_layout(guides = 'collect')
Created on 2021-08-03 by the reprex package (v2.0.0)

ggsave with non-ASCII plotmath labels using cairo

I have a non-ASCII axis label with a plotmath expression. When I try to save as png using cairo, I get an error:
library(ggplot2)
ggsave("test.png",
qplot(mtcars$hp, mtcars$cyl) +
ylab(expression(`cÜl`~italic(r)(italic(M)))) +
xlab(expression(hp~italic(hp))),
device = grDevices::png,
type = "cairo")
The error message is:
Metric information not available for this family/device
On the other hand, using the "windows" device works (except for a warning):
ggsave("test.png",
qplot(mtcars$hp, mtcars$cyl) +
ylab(expression(`cÜl`~italic(r)(italic(M)))) +
xlab(expression(hp~italic(hp))),
device = grDevices::png,
type = "windows")
The warning (in German) is:
In dev(filename = filename, width = dim[1], height = dim[2], ...) :
'width=7, height=7' sind unwahrscheinliche Pixelzahlen
Finally, non-ASCII axis labels are not a problem per se, if the label is not a plotmath expression:
ggsave("test.png",
qplot(mtcars$hp, mtcars$cyl) +
ylab("cÜl") +
xlab(expression(hp~italic(hp))),
device = grDevices::png,
type = "cairo")
The last command raises no error.
However, I would prefer to use cairo, since it draws nicer pictures sometimes. Any ideas?
This worked on a Windows machine with R 4.0.2 (and also on linux):
library(ggplot2)
library(ggtext)
ggsave("test.png", width = 6, height = 6,
qplot(mtcars$hp, mtcars$cyl) +
labs(x = "hp *hp*",
y = "c\u00DCl *r*(*M*)") +
theme(
axis.title.x = element_markdown(),
axis.title.y = element_markdown()
),
type = "cairo-png")
Created on 2020-07-07 by the reprex package (v0.3.0)
This works for me (though I am not on windows); try leaving out the device parameter:
library(ggplot2)
ggsave("test.png",
qplot(mtcars$hp, mtcars$cyl) +
ylab(expression(`cÜl`~italic(r)(italic(M)))) +
xlab(expression(hp~italic(hp))),
type = "cairo-png")
#> Saving 7 x 5 in image
Created on 2020-07-05 by the reprex package (v0.3.0)

R studio only export part of figure if I set font family in ggplot2

Update:
When I used ggsave() or pdf() to save the figure, it works but with warning:
font family 'Times-Roman' not found, will use 'sans' instead
Actually, I have this font installed in my OS, and R studio can display it correctly. And output to bitmap files are well, such as PNG, TIFF. The problem only happen when outputting to PDF files. Maybe something goes wrong in my OS ENV.
Thank you for the help.
When I exported the figure to pdf by clicking the Export button in R studio, I found that once the font family was set, the exported pdf file would only contain a portion of my figure.
Is it the bug or just somethings I am wrong?
Here are my code and result:
R version 3.5.2 (2018-12-20) -- "Eggshell Igloo"
Platform: x86_64-apple-darwin16.7.0 (64-bit)
library('ggplot2')
library('gridExtra')
x = c(1:30)
y1 = 1.3^x + 10
y2 = x
class = c(rep('A',14),'B',rep('A',14),'D')
df1 = data.frame(x=x,y=y1,class = class)
df2 = data.frame(x=x,y=y2,clas = class)
P1 <- ggplot(df1,aes(x=x,y=y1,fill=class)) + geom_bar(stat = "identity") +
theme(text = element_text(family = 'Times-Roman'))
P2 <- ggplot(df2,aes(x=x,y=y2,fill=class)) + geom_bar(stat = "identity") +
theme(text = element_text(family = 'Times-Roman'))
grid.arrange(P1,P2,ncol=2)
And I cannot get the whole figure after exporting

ggplot2 doesn't show Chinese character properly in rstudio-server in docker

I try to use ggplot2 to plot a chart with the Chinese title but shows Unicode in a square.
I've tried some following command
quartz(family='STKaiti')
par(family='STKaiti')
plot(1, xlab = "你好", family = "Heiti SC Light")
and use "extrafont" font to load my ubuntu fonts into R
The characters plot shows are still Unicode in a square. I want to show the Chinese word properly.
Still, I have no idea how to call this kind of words. "Unicode in a square" is the best I can describe.
Try the showtext package, which was designed for this.
Sample code:
library(ggplot2)
library(showtext)
showtext_auto()
p = ggplot(NULL, aes(x = 1, y = 1)) + ylim(0.8, 1.2) +
annotate("text", 1, 1, size = 15, label = "你好,世界") +
xlab("坐标轴") +
theme_bw(base_family = "wqy-microhei", base_size = 24)
quartz()
print(p)

comfortable way to use unicode characters in a ggplot graph

Is there a good practice to insert unicode characters in a ggplot title and also save it as pdf?
I am struggling with expression, paste and sprintf to get a nice title...
So, what works is
ggtitle(expression(paste('5', mu, 'g')))
This will print an ugly greek mu. By ugly I mean a different font, but overall, it will be printed as pdf without problems. But the problems start, if you want to have new lines in the title. Or maybe I didn't found a solution for this.
My preferred solution would be to use sprintf with the unicode number, so for example
ggtitle(sprintf('5\u03BCg'))
It shows a nice result on the screen but it is not possible to save as pdf with ggsave. PNG works fine, but I would like to use the pdf save option.
Is there a possibility to plot the unicode characters with ggsave? I read about the cairo_pdf device, but this messes up the fonts and I can not save the plot properly.
Thanks in advance for any help.
EDIT:
Example PDF
I just uploaded an example PDF... So maybe my problem is somewhere else...
Try
library(ggplot2)
p <- ggplot(df, aes(x=date, y=value))
p <- p + geom_line()
p + ggtitle(sprintf('5\u03BCg'))
library(Cairo)
ggsave("newfile.pdf", device=cairo_pdf)
data
set.seed(42)
df <- data.frame(date = 1:10 , value = cumsum(runif(10 , max = 10)) )
Using the emojifont package fixes this issue for me.
library(emojifont)
I am sharing the tricks to have Unicode characters properly displayed on PDF files. I am currently running R-4.0.5 for Windows.
library(ggplot2)
library(gridExtra)
library(grid)
library(png)
#--- The trick to get unicode characters being printed on pdf files:
#--- 1. Create a temporary file, say "temp.png"
#--- 2. Create the pdf file using pdf() or cairo_pdf(), say "UnicodeToPDF.pdf"
#--- 3. Combine the use of grid.arrange (from gridExtra), rasterGrob (from grid), and readPNG (from png) to insert the
# temp.png file into the UnicodeToPDF.pdf file
test.plot = ggplot() +
geom_point(data = data.frame(x=1, y=1), aes(x,y), shape = "\u2191", size=3.5) +
geom_point(data = data.frame(x=2, y=2), aes(x,y), shape = "\u2020", size=3.5) +
geom_point(data = data.frame(x=1.2, y=1.2), aes(x,y), shape = -10122, size=3.5, color="#FF7F00") +
geom_point(data = data.frame(x=1.4, y=1.4), aes(x,y), shape = -129322, size=3.5, color="#FB9A99") +
geom_point(data = data.frame(x=1.7, y=1.7), aes(x,y), shape = -128515, size=5, color="#1F78B4") +
ggtitle(sprintf('5\u03BCg'))
ggsave("temp.png", plot = test.plot, width = 80, height = 80, units = "mm")
#--- Refer to http://xahlee.info/comp/unicode_index.html to see more unicode character integers
pdf("UnicodeToPDF.pdf")
grid.arrange(
rasterGrob(
readPNG(
"temp.png",
native=F
)
)
)
dev.off()
file.remove("temp.png")

Resources