Saving ggplot graph to PDF with fonts embedded in r - r

I've been following advice I've found online for saving a ggplot graph to PDF but I can't quite get it to work. I'm using the extrafont package to produce charts with text in Calibri, but my charts are printing out with no text. I don't know what I'm missing. I can't find any mistakes in my process. Hopefully, someone else can help.
Here's the code and process I used:
library(extrafont)
font_import(pattern="[C/c]alibri")
loadfonts(device="win")
I installed GhostScript at this time. Then ran the following to set the GhostScript location.
Sys.setenv(R_GSCMD = "C:\\Program Files\\gs\\gs9.21\\bin\\gswin64c.exe")
I then produced a chart using ggplot called "chart". The chart looked perfect in RStudio, but not in PDF.
ggsave("chart.pdf", plot = chart, width = 6, height = 4)
Here I get warnings showing stuff like this:
In grid.Call(C_textBounds, as.graphicsAnnot(x$label), ... : font family 'Calibri' not found in PostScript font database
Apparently, these warnings are supposed to happen? Then I run...
embed_fonts("chart.pdf", outfile="chart_embed.pdf")
Unfortunately, after all this, the final "embed" chart looks no different than the original chart produced, neither of which have any text.
In case it helps, here's the code to produce the chart:
a <- ggplot(data=stats, aes(x=Date))
Chart <- a + geom_point(aes(y=NevadaTotalNonfarmAllEmployees)) +
xlab("Date") +
ylab("Nonfarm Jobs") +
ggtitle("Nevada Total Jobs") +
theme(axis.title.x = element_text(size=15, family = "Calibri"),
axis.title.y = element_text(size=15, family = "Calibri"),
axis.text.x = element_text(size=10, family = "Calibri"),
axis.text.y = element_text(size=10, family = "Calibri"),
plot.title = element_text(hjust=0.5, size=20, family = "Calibri"))
I've been pulling my hair out trying to figure this out. Or maybe it's not the code but something else? Either way, thanks for any assistance.

There are a couple issues at play here: (1) loading fonts into R and (2) using a PDF-writing library that works correctly with custom embedded fonts.
First, as others have mentioned, on Windows you generally need to run extrafont::font_import() to register many of your system fonts with R, but it can take a while and can miss TTF and other types of fonts. One way around this is to load fonts into R on the fly, without loading the full database, using windowsFonts(name_of_font_inside_r = windowsFont("Name of actual font")), like so:
windowsFonts(Calibri = windowsFont("Calibri"))
This makes just that one font accessible in R. You can check with windowsFonts(). You have to run this line each time the script is run—the font loading doesn't persist across sessions. Once the font has been loaded, you can use it normally:
library(tidyverse)
df <- data_frame(x = 1:10, y = 2:11)
p <- ggplot(df, aes(x = x, y = y)) +
geom_point() +
labs(title = "Yay Calibri") +
theme_light(base_family = "Calibri")
p
Second, R's built-in PDF-writing device on both Windows and macOS doesn't handle font embedding very well. However, R now includes the Cairo graphics library, which can embed fonts just fine. You can specify the Cairo device in ggsave() to use it, which is easier than dealing with GhostScript:
ggsave(p, filename = "whatever.pdf", device = cairo_pdf,
width = 4, height = 3, units = "in")

I’ve found it safer to explicitly register fonts using pdfFonts (and/or postscriptFonts).
The documentation contains an example but also take a look at my fonts module. With this, registering a new font is as easy as writing
fonts$register_font('Calibri')
Internally, this creates a font specification using Type1Font, ensures that names are set correctly, and invokes pdfFonts.
It also ensures that the complete set of font metrics to exist (which is done using extrafont::ttf_import).
This way is considerably faster than generating font metrics for all fonts using font_import, and it gives you more control.

I think you missed the initialization step font_import(). Be forewarned, executing this command can take a bit longer time.
First, you can see what fonts you have available with the command windowsFonts(). The current fonts in my graphing device are;
$serif
[1] "TT Times New Roman"
$sans
[1] "TT Arial"
$mono
[1] "TT Courier New"
Thereafter, you can import the extrafont library and the loadfonts(device = "win"). I also recommend to execute these commands in the R console and not in RStudio. I suggest this because when you are importing the fonts using font_import() in RStudio, it may not show the y/n prompt.
Below I provide a minimum reproducible example;
library(ggplot2)
library(extrafont)
font_import()
# tell where ghostscript is located. This is required for saving the font in pdf
Sys.setenv(R_GSCMD = "C:\\Program Files\\gs\\gs9.21\\bin\\gswin64c.exe") # I have installed 64-bit version of GhostScript. This is why I've used gswin64c.exe. If you have installed 32-bit version of GhostScript, use gswin32c.exe. Failure to specify the correct installed GhostScript will yield error message, "GhostScript not found"
# create a plot object
p <- ggplot(mtcars, aes(x=wt, y=mpg)) +
geom_point()+
ggtitle("Fuel Efficiency of 32 Cars")+
xlab("Weight (x1000 lb)") + ylab("Miles per Gallon") +
theme_bw()+
theme(text=element_text(family="ArialMT", size=14))
# show the plot
print(p)
# save the plot as pdf
ggsave("figures//ggplot_arialmt.pdf", p, width=20, height=20,
device = "pdf", units = "cm")
Note
Its only the ArialMT font that seems to work with ggsave(). See this SO post. Using any other font for saving to pdf, renders the figure with characters on top of another. This is also an open issue for ggsave and has not been answered since 2013.

Related

R plot values using dice font?

I would like to create a plot in R using dice font for values 1 to 6. Dice font for windows can be downloaded here - copy the downloaded true type font to the C:\Windows\Fonts directory and it can be used in windows applications like Excel or Word.
I found out about the showtext package in this question for adding fonts to R which seems to add the dice font using the R script below.
require(showtext)
font_add(family = "dice",regular = "C:/Users/Mark/AppData/Local/Microsoft/Windows/Fonts/dice.ttf")
For some reason, I don't understand I had to set the path to the AppData/Local directory to get font_add to no report a could-not-find-it error. The next challenge was to get was to make a simple test plot
plot(c(1,2),c(2,1),pch = 0, col = "blue", type = "p", cex =5)
text(c(1,2),c(2,1),c(2,1),col = "red")
However, when I attempt to use the dice font using the text funtion I get an error ...
font family not found in Windows font database
text(c(1,2),c(2,1),c(2,1),col = "red", family = "dice")
Questions:
Is there a way to display the fonts accessible to R so I can determine if the dice font is available?
If dice font is available then how do I get the font working with the text function?
Is there an alternative or better way to approach this idea?
After exploring the example suggested by Andrew Brēza I managed to get a result using ggplot2 - I could not find a solution for base R. With respect to the three questions I listed in the original post
showtext has two functions to list the font families and fonts available to are respectively
font_families()
font_files()
I also found that I needed to install dice font using the windows right-click option 'install for all users' else the font file was installed under a user AppData/Local directory not the C:\Windows\Font directory
2.showtext does not appear to work with the base R text function even though the fonts are listed as available - I therefore explored ggplot
3 ggplot with showtext is the only working solution - script below produces the results I was looking for - I will just have to spend a bit of time making it look like a base R plot
# Plot numbers using dice font
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# https://stackoverflow.com/questions/34522732/changing-fonts-in-ggplot2
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
require(showtext)
# Note install the dice font using right-click install for all users
# Otherwise the font file is install in user profile nto C:\Windows\fonts
# Add the dice font to R
font_add(family = "dice",regular = "C:/Windows/Fonts/dice.ttf")
# Checks to show the dice font available in the fonts available to R
font_families()
font_files()
# Automatically use show text for newplots - do I need this?
showtext_auto()
# Load ggplot2
require(ggplot2)
# Create some data
df <- data.frame(rbind(c(1,2,2),c(2,1,4)))
# Plot the dice values
ggplot(df, aes(x = X1, y = X2)) +
geom_point(size = 0.1, shape = 0) +
annotate("text",df[1,1],df[1,2], label = df[1,3], family = "dice", size = 10) +
annotate("text",df[2,1],df[2,2], label = df[2,3], family = "dice", size = 10)

How to preserve colors saving from ggplot?

This may not be the right place to ask this question, but I'm having trouble saving my colors from ggplot. I made this plot (pic below), and used ggsave() to save it as a .png file, and I loved the way it looked. However, when I take that .png file and upload it anywhere (specifically, in this case, to twitter and UpWork), the colors distort. The blue and orange get much darker, and I like the plot much less. Why is this happening? Is it the way I'm saving? Is it a function of file compression on those websites?
Can anyone recommend a better way to save that will not influence the aesthetics of my plots?
Attached here are screenshots of what you can see on the file on my computer (first pic), and a screenshot of the uploaded version of that same exact file (second pic. Darker). Hopefully they both upload as they look to my computer here...
Here is an example of the code/colors I am using:
require(ggplot2)
plot <- ggplot(data=data.frame(x=c(1:3),y=c(1:3)),
aes(x=x,y=y))+
geom_point(col="#E56800", size=3)+
theme_classic()+
theme(panel.background = element_blank(),
plot.background = element_rect(fill = "#354154"),
text= element_text(color="#FCFFF9"),
axis.text = element_text(color="#FCFFF9"))
ggsave(plot, filename = "plot.png",
width = 5, height = 7,
dpi=300)
EDIT: By the way, I'm using RStudio on a Macbook Pro, in case that's relevant. I always get confused by the graphical device options, so I'm guessing they have something to do with this.
You can try to install the CRAN Cairo package, and add a type argument in ggsave like this:
ggsave(plot, filename = "plot.png",
width = 5, height = 7,
dpi=300,
type = "cairo-png") # add this argument
Cairo allows to export anti-aliased images (this is the default on Mac but not on PC), maybe this could help.

Fonts not loading in showtext font_add_google

I'm trying to graph some data and my code looks like this:
library('ggplot2')
library('tidyr')
library('ggthemes')
library('showtext')
font_add_google('Syncopate', 'Syncopate')
showtext_auto()
ggplot(aes(x = X, group=1), data = glassdoor)+
geom_line(aes(y = col1, color = 'red'))+
geom_line(aes(y = col2, color = 'blue'))+
geom_line(aes(y = col3, color = 'magenta'))+
geom_line(aes(y = col4, color = 'yellow'))+
theme(text = element_text(family = "Syncopate"))+
ggtitle('A Long Test Title')
Syncopate is a distinctive font, seen here. But my visualization's font just looks like this (this is a test graph, ignore its overall poorness):
But if I load a system theme like Times New Roman, it works fine. Why aren't my google fonts loading using showtext?
Edit
Jrakru's answer works, but bear in mind that you have to run that entire code block: The new fonts will appear in a saved png file, but not in the preview window. This isn't written as a slight against the answer, but rather for others like myself who expect the fonts to show up in the RStudio console and therefore omit the ggsave and png portions of the code.
The GitHub for showtext mentions
This example should work on most graphics devices, including pdf(),
png(), postscript(), and on-screen devices such as windows() on
Windows and x11() on Linux.
If you read really really hard between lines, that means, that RStudioGD graphics device is not supported. I did not see that the first few times I read it. I only know because the vignette is a little more explicit.
NOTE: Currently showtext does not work with the built-in graphics
device of RStudio, hence to try the code below, it is suggested to run
the code in original R console, or use other graphics devices such as
x11() and windows()
see
https://cran.rstudio.com/web/packages/showtext/vignettes/introduction.html
With the above knowledge, we can do this:
library('tidyr')
library('ggthemes')
library('showtext')
font_add_google("Schoolbell", "bell")
showtext_auto()
library('ggplot2')
df<- data.frame(x=1:10, y=101:110)
options("device" = "windows")
win.graph(10,10,12)
ggplot(data = df) +
geom_line(aes(x,y))+
theme(text = element_text(family = "bell"))+
ggtitle('A Long Test Title')
ggsave("showtext-example.png", width = 7, height = 4, dpi = 96)
options("device" = "RStudioGD")
And Voila!
Ps: I assumed you are a windows user.
according to the same document: https://cran.rstudio.com/web/packages/showtext/vignettes/introduction.html
And the very bottom of it, you can read this:
Compatibility with RStudio
Starting from version 0.9, showtext can work well with the RStudio
graphics device (RStudioGD). Simply call showtext_auto() in the
RStudio session and then the plots will be displayed correctly.
it worked for me in RStudio 1.3.959

Embedded pdf-font in R-plot is not recognized by InDesign although available

Using ggplot2, extrafont and R's pdf device I have built plots in the cmyk colormodel that incorporate certain non-Windows fonts. The pdf-output looks fine and shows that the font has been embedded correctly, for instance "Arial-BoldMT".
Unfortunately, when trying to import the pdf into Adobe InDesign, I get the error message that the font "Arial-BoldMT" is not currently available, which also happens to the non-Windows fonts I mentioned above.
I suppose there might be a problem with the name of the embedded font that cannot be recognized by InDesign, since the font is very well available as "Arial" including all the variations such as "bold".
Any suggestions how to get those fonts working in InDesign by either adjusting the R script or using InDesign?
Thank you!
Here is a sample plot, similar to the plots I need to produce, just leaving out the unnecessary code lines:
library(ggplot2)
library(extrafont)
# define font
font <- "Arial"
# sample data
x <- data.frame(c("Personnel Costs", "Non-Personnel Costs", "Investments"),
c(33, 22, 45))
colnames(x) <- c("costs", "percent")
# plot
plot <- ggplot(x, aes("", y = percent, fill = factor(costs), width = 1.2))+
geom_bar(width = 4, stat="identity")+
# add the text (no font specification here)
geom_text(aes(label=costs),fontface = "bold")+
# no legend
theme(legend.position = "none") +
# pie-chart
coord_polar("y", start = 0.42, direction = 1)
# save plot
pdf("plot.pdf", family=font, colormodel="cmyk")
plot
dev.off()
PS: Using ggsave and embedFonts() with Ghostscript produced the same results.
Note: Using "Calibri" with the pdf device or ggsave and embed_fonts() does not work at all.
It seems if the font was not properly embedded into the pdf.
By running embed_fonts() after saving the plot, the according font got embedded and now works in InDesign.
I just needed:
library(extrafont)
embed_fonts(file="plot.pdf", outfile="plot.pdf")

Export to pdf not displaying properly in ggplot2

I have a complex figure P made up of figures Fig_NPK and Barchart_fert, they were made using a datasheet "Fert" with columns including "Vil", "N", "P", and "K". My goal is to create a pdf file and use ghostscript to embed the "Times New Roman" font family in the pdf file. When I use ggsave to export "P" to a pdf file it doesn't display properly. The code used were:
library(extrafont)
library(ggplot2)
Figures, Fig_N as an example (Fig_N, P, and K form Fig_NPK)
Fig_N<-ggplot(aes(y = N, x = factor(Vil)), data = Total_fac[which(Total_fac$N<quantile(Total_fac$N,0.95)&Total_fac$N>quantile(Total_fac$N,0.05)),])+stat_boxplot(geom ="errorbar") + geom_boxplot() +ggtitle("N requirement")+labs(x="Village",y="Amount used (kg)") +theme(text=element_text(family="Times New Roman", face="plain", size=14))
Fig_NPK<-plot_grid(Fig_N,Fig_P,Fig_K, nrow=3,align = "v")
Barchart_fert<-ggplot(Fert, aes(x=Village, y=Amount, fill=Fertilizer)) + geom_bar(stat = "identity", width=0.4)+ggtitle("Fertilizer usage")+ylab("Amount used (kg)")+theme(axis.text.x=element_text(vjust = 0.5))+scale_fill_discrete(name="Fertilizer type", breaks=c("N-Eq.", "P2O5-Eq.", "K2O-Eq."),labels=c("N Eq.", expression('P'[2]*'O'[5]~~Eq.), expression('K'[2]*'O'~~Eq.)), c=60, l=80)+theme(text=element_text(family="Times New Roman", face="plain", size=14))
P<-ggdraw() + draw_plot(Fig_NPK,0,0,.4,1)+draw_plot(Barchart_fert,.4,0,.6,1) + draw_plot_label(c("A", "B"), c(0,.4), c(1,1), size=14)
ggsave("FigP.pdf", plot=P, width=5, height=5)
Error message after ggsave:
Error in grid.Call.graphics(L_text, as.graphicsAnnot(x$label), x$x, x$y, : Metric information not available for this family/device In addition: There were 50 or more warnings (use warnings() to see the first 50)
The resulting pdf file is incomplete. The same thing happens when I try exporting "P" to a postscript file. I have been following the help file and other answers on embedding fonts but can't seem to solve my issue.
Found a solution in this answer. Adding
device=cairo_pdf
in ggsave does solve the problem of not display the correct font in pdf and tiff files, though as #user1092247 pointed out, the kerning seems awkward. Would still appreciate it if anyone could perfect this solution, and explain a bit more on what the problem actually was.
Indirect way-
Save the image as png in R-studio. Covert png to pdf using other software (such as inkspace - change settings in Document properties).

Resources