I have created some awesome graphs that I want to export to my Word document. Yea, should write in Markdown but... you know... someday!
However, how do I resize the graphs to the right dimensions while labels stay "within" the perimeter? See the following examples (code is at the end of the document).
I want to insert the following graph into my word document:
Looks great! Not when I insert it into the document:
Labels are two tiny, and I would love to stretch it vertically, so the width is greater than the height. So I managed to produce this:
And this is were I am stuck. How do I keep the labels within the perimeters? And is there a better way to "fit" the word document than guessing correct dimensions?
Thanks!
This is the code:
library(ggplot2)
df <- mpg # Load sample data
# First test graph
ggplot(data = df, mapping = aes(cyl, hwy)) +
geom_smooth() +
geom_point() +
geom_point() +
labs(y = "This is just one very long label to prove a point ..... 1234",
x = "Cyl") +
theme_classic() +
theme(legend.title = element_blank())
ggsave("test1.png")
# Modified test graph to add fit the Word document
ggplot(data = df, mapping = aes(cyl, hwy)) +
geom_smooth() +
geom_point() +
geom_point() +
labs(y = "This is just one very long label to prove a point ..... 1234",
x = "Cyl") +
theme_classic(base_size = 12) + # SIZE CHANGED
theme(legend.title = element_blank())
ggsave("test2.png", width = 8, height = 4) # DIMENSIONS DEFINED
A solution I tend to use involves the officer package as mentioned above. This used to be able export graphs as vector objects to docx so you could change sizes and text in the graph when it's in the document. This seems to have been suspended in recent versions, but still works for powerpoint. The following code puts the graph as a grouped shape in a powerpoint slide where you can tweak it before copying into word:
library(ggplot2)
library(officer)
library(tidyverse)
df <- mpg # Load sample data
# First test graph
plot2 <- ggplot(data = df, mapping = aes(cyl, hwy)) +
geom_smooth() +
geom_point() +
geom_point() +
labs(y = "This is just one very long label to prove a point ..... 1234",
x = "Cyl") +
theme_classic(base_size = 12) + # SIZE CHANGED
theme(legend.title = element_blank())
pptx <- read_pptx()
pptx %>%
add_slide() %>%
# This first line puts it in as a static png image for comparison
ph_with(plot2, location = ph_location_type(type = "body")) %>%
add_slide() %>%
# This line puts in a shape object, which can be ungrouped and edited
ph_with(rvg::dml(ggobj = plot2),
width = 8,
height = 4,
location = ph_location_type(type = "body"))
#> pptx document with 2 slide(s)
print(pptx, "test_graph.pptx")
Created on 2020-12-08 by the reprex package (v0.3.0)
That's a sort of tweaky solution which at least allows you visual control over sizes. This used to be more easily provided through the export package (available on GitHub), but it's not on CRAN anymore and behind the scenes used the now defunct parts of officer to put vector graphics in docx documents.
Edit: See this issue on GitHub for an explanation of why vector graphics to docx is no longer an option through officer.
Related
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)
I am using R studio / R Markdown to create plots, some with ggplot, some with base R function. I would like to insert a caption for each of my plots which contains the legend similar to the example shown here:
Can anyone suggest how to place the legend of my plots (built with ggplot and base R functions) within the caption as shown in this example?
I searched online and found out that it is possible to use something like:
p + labs(caption="Figure S1: This is the Figure Legend")
however, I could not find how to embed the legend into the caption, and I also could not find a solution for plots made using base R.
There are some solutions that require Latex, but I cannot use Latex for this project.
You could just push the legend to the bottom and add a custom title - inlcude a counter to get numbered Plots:
library(ggplot2)
# using the internal iris dataset
iris
# set counter to zero
NR <- 0
# Add counter and build plot
NR <- NR + 1
legend <- paste0("Fig. ", NR, ": This is a Plot about...:")
ggplot2::ggplot(iris, aes(Sepal.Length, Petal.Width, color = Species)) +
ggplot2::geom_point() +
ggplot2::labs(color= legend) +
ggplot2::theme(legend.position = "bottom")
# Add counter and build second plot
NR <- NR + 1
legend <- paste0("Fig. ", NR , ": This is a Plot about...:")
ggplot2::ggplot(iris, aes(Sepal.Width, Petal.Length, color = Species)) +
ggplot2::geom_point() +
ggplot2::labs(color= legend) +
ggplot2::theme(legend.position = "bottom")
I am trying to create a plot title manually formatted on two lines which includes two italicized words, I have done some searching
on Stack Exchange but have not found a good solution to this seemingly simple problem.
The scientific names of the two species are fairly long, and thus the need for a multi-line title (ggplot2 doesn't format this).
Objective:
..........First Line of Title with Species
Second line words anotherItalicSpecies the end
ggplot(mtcars,aes(x=wt,y=mpg))+
geom_point()+
labs(title= expression(paste(atop("First line of title with ", atop((italic("Species")))),"
secondline words", italic("anotherSpecies"), "the end")))
Which yields the following mangled title:
Using a combination of atop, paste, italic and scriptstyle:
ggplot(mtcars, aes(x = wt, y = mpg)) +
geom_point() +
labs(title = ~ atop(paste('First line of title with ',italic("Species")),
paste(scriptstyle(italic("Species")),
scriptstyle(" secondline words "),
scriptstyle(italic("anotherSpecies")),
scriptstyle(" the end"))))
gives you the desired result:
Using scriptstyle is not a necessity, but imho it is nicer to have your subtitle in a smaller font than the main title.
See also ?plotmath for other usefull customizations.
As an alternative to inserting line breaks in title, you may use title together with subtitle (available from ggplot 2.2.0). Possibly this makes the plothmathing slightly more straightforward.
p <- ggplot(mtcars, aes(x = wt, y = mpg)) +
geom_point() +
labs(title = expression("First line: "*italic("Honorificabilitudinitatibus")),
subtitle = expression("Second line: "*italic("Honorificabilitudinitatibus praelongus")*" and more"))
p
If you wish the font size to be the same on both lines, set the desired size in theme.
p + theme(plot.title = element_text(size = 12),
plot.subtitle = element_text(size = 12))
Note that both title and subtitle are left-aligned by default in ggplot2 2.2.0. The text can be centered by adding hjust = 0.5 to element_text above.
We could also call cowplot::draw_label() two times (inspired from this discussion). However, we need to tweak a bit the position and make enough space for the custom title. I gave more explanations about this approach and also using ggplot2::annotation_custom() in ggplot2 two-line label with expression.
library(ggplot2)
library(cowplot)
#>
#> Attaching package: 'cowplot'
#> The following object is masked from 'package:ggplot2':
#>
#> ggsave
# The two lines we wish on the plot. The ~~ creates extra space between the
# expression's components, might be needed here.
line_1 <- expression("First Line of Title with" ~~ italic("Species"))
line_2 <- expression(italic("Species") ~~ "second line words" ~~ italic("anotherSpecies") ~~ "the end")
# Make enough space for the custom two lines title
p <- ggplot(mtcars, aes(x = wt, y = mpg)) +
geom_point() +
labs(title = "") + # empty title
# Force a wider top margin to make enough space
theme(plot.title = element_text(size = 10, # also adjust text size if needed
margin = margin(t = 10, r = 0, b = 0, l = 0,
unit = "mm")))
# Call cowplot::draw_label two times to plot the two lines of text
ggdraw(p) +
draw_label(line_1, x = 0.55, y = 0.97) +
draw_label(line_2, x = 0.55, y = 0.93)
Created on 2019-01-14 by the reprex package (v0.2.1)
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")
I'd like to add a footnote citation to my 3-panel facet grid plot produced in R. It's a footnote to credit the data source. I'd ideally like to have it below and external to all three axes---preferably in the lower left.
I'm using ggplot2 and also ggsave(). This means I can't use grid.text()-based solutions, because that only draws on the x11() window, and can't be added to the ggplot object.
Using instead png() ...code... dev.off() does not appear to be an option because I need ggsave's resizing parameters, and find this command produces better, clearer prints (that are also much faster, because I'm not printing to the screen).
Here's my basic code:
p1 <- ggplot(data, aes(date, value))
facet_grid(variable ~ .) + geom_point(aes(y =value), size=1) +
theme_bw() +
opts(title=mytitle)
print(p1)
ggsave("FILE.png",width=mywidth, height=myheight, p1, dpi=90)
I've tried:
p1 <- ggplot(data, aes(date, value))
facet_grid(variable ~ .) + geom_point(aes(y =value), size=1) +
theme_bw() +
opts(title=mytitle)
print(p1)
grid.text(unit(0.1,"npc"),0.025,label = "Data courtesy of Me")
grid.gedit("GRID.text", gp=gpar(fontsize=7))
ggsave("FILE.png",width=mywidth, height=myheight, p1, dpi=90)
This appropriately puts the footnote in the lower left corner on the x11() display, external to the plots, but unfortunately, since it isn't applied to the p1 object, it isn't saved by the ggsave command.
I've also tried:
p1 <- ggplot(data, aes(date, value))
facet_grid(variable ~ .) + geom_point(aes(y =value), size=1) +
theme_bw() +
opts(title=mytitle) +
annotate("text", label = "Footnote", x = 0, y = 10, size = 5, colour = "black") +
print(p1)
ggsave("FILE.png",width=mywidth, height=myheight, p1, dpi=90)
This successfully prints using ggsave, however it has the following problems:
It is repeated 3 times, in each of the 3 facets, rather than 1 time.
It is contained within the plots, rather than external to them.
Text is difficult to place---seems to be using plot units (my x-axis is date, so 0 puts it around 1970).
The text size doesn't seem to change despite my size parameter.
A couple of related links from when I explored this...
ggplot2 footnote
(doesn't work with ggsave)
How to label the barplot in ggplot with the labels in another test result?
(is inside the plot, not external/below plot)
Different font faces and sizes within label text entries in ggplot2
(doesn't work with ggsave)
problem saving pdf file in R with ggplot2
ggplot2 now has this ability natively with no need for additional packages. ... + labs(caption = "footnote", ...)
library(ggplot2)
ggplot(diamonds, aes(carat, price, color = clarity)) +
geom_point() +
labs(title = "Diamonds are forever...",
subtitle = "Carat weight by Price",
caption = "H. Wickham. ggplot2: Elegant Graphics for Data Analysis Springer-Verlag New York, 2009.")
library(gridExtra)
library(grid)
library(ggplot2)
g <- grid.arrange(qplot(1:10, 1:10, colour=1:10) + labs(caption="ggplot2 caption"),
bottom = textGrob("grid caption", x = 1,
hjust = 1, gp = gpar(fontface = 3L, fontsize = 9)))
ggsave("plot.pdf", g)
Edit: note that this solution is somewhat complementary to the recent caption argument added to ggplot2, since the textGrob can here be aligned with respect to the whole figure, not just the plot panel.
Adding to the answer of Brandon Bertelsen: if you want to have the caption in the left corner, add
theme(plot.caption = element_text(hjust = 0))