I'm creating some R scripts. In one of them, I would like to write formatted text enclosed in a box to a png. I don't know how many lines of text there are, or what the length of the longest line is until I get into the R script, but I want to keep the formatting of the line and have the text fairly tightly enclosed. When I use a plot and a textbox, the plot comes with a large amount of graphical baggage and undesired behavior.
Is there anything that displays text on the device area that
does not require a plot,
wraps lines if they exceed a desired width, and
tightly surrounds the final text with a box?
You can use ggtext::geom_textbox() in conjunction with theme_void():
library(ggplot2)
library(ggtext)
txt <- "All human beings are born free and equal in dignity and rights. They are endowed with reason and conscience and should act towards one another in a spirit of brotherhood."
ggplot() +
geom_textbox(
aes(x = 0, y = 0, label = txt),
size = 18 / .pt,
width = unit(6, "inches")
) +
theme_void()
You’ll likely need to play with font size, box size, and plot size.
Related
I would like to find an easy solution to numbering subfigures as this is a very standard exercise of my work. I could do this by arranging the plots and automatically adding number via e.g. egg::ggarrange(). However, this gets complicated and especially ugly if I have a ggplot that is already split into facets via facet_grid() and with a long strip text. I already asked a similar question here.
In publications I would usually want to have subfigures with a label at the top left or right corner like 1, 2, 3... or A, B, C,... and subfigure text label describing the facet centered on top. Both, the label and the text should be independent from each other. Looking at the solution of #stefan in my above mentioned question, the labels and text are obviously not independent from each other and the labels are not left-aligned.
I wonder, is there maybe a function that puts labels like 1, 2, 3... or A, B, C,... left-aligned on top of the top-right corner of the facet independent of the (centered) strip text itself? That would be awesome and would save me a lot of hassle.
I could obviously just use a label like "<b>1</b> Text label" and left align it. But this looks really ugly if I have a very long text. What I want to achieve is rather a numeric label on the left and a text label spanning two lines.
An acceptable solution would be to split the strip text into two columns that are independent from each other. This way I could put a number left-aligned and centered a text label over two lines.
Thanks to #stefan I had a look at the tagger package. I find the tag_facets() function to be a bit hard to work with (especially the positioning).
However, I noticed that I already have the tag_facet() function (without the s!) from the egg package and decided to give it a try. This changes the margins of the plot in an unfortunate way and sets strip text to element_blank(), but this is pretty easy to revert (similar solution presented here in the answer by #Lyngbakr).
I just add this to my plot and it works nicely:
egg::tag_facet(p, tag_pool = 1:5, open = "", close = "", vjust = -0.7) +
coord_cartesian(clip = "off") +
theme(strip.text = element_text(),
legend.margin=margin(0,0,0,0),
legend.box.margin=margin(-10,-10,-10,-10))
(Although it would be more intuitive, this does not seem to work with the egg::tag_facet_outside() function though...)
Within R-Studio, I am generating plots with ggplot, then I save them with ggsave() for further use (I know, not ideal, but non-optional right now).
My problem is that when I generate the plot before saving it, R shows it to me in a particular size. With ggsave, I set width and height, so the elements displayed shift etc. I only see this after saving the plot.
I want R to show it to me before. I thus assume that I need to set the size of the plot within ggplot() somewhere , not in ggsave().
How can I do this in the least complicated fashion?
library(ggplot2)
ggplot(mtcars, aes(mpg,disp)) + geom_point() +
labs(title="Rocket science title that will get cut by ggsave")
ggsave("rocketScience.png", width=10, height=7, unit="cm")
You can use the set_panel_size() function from the egg package.
With this function you can fix the panel size of the plot. This can be very useful when creating multiple plots that should have the exact same plotting area but use varying axis labels or something similar that would usually slightly change the panel dimensions. Especially useful for presentations with seamless animations or publications. It also ensures the same dimensions in the preview and the saved plot.
p <- ggplot(mtcars, aes(mpg,disp)) +
geom_point() +
labs(title="Rocket science title that will get cut by ggsave")
#to view the plot
gridExtra::grid.arrange(egg::set_panel_size(p=p, width=unit(5, "cm"), height=unit(7, "cm")))
#to save the plot
ggsave(filename = "myplot.pdf", plot = egg::set_panel_size(p=p, width=unit(5, "cm"), height=unit(7, "cm")))
Within ggsave you can still manipulate the size of the whole "page" saved, but this will only influence the amount of white space around the plot. The actual panel size will stay fixed.
The example plot from above with 5cm or 15cm as width:
I don't believe this is achievable via ggplot settings; you might get around it if using RMarkdown, as you can set with and height of an output of a markdown chunk via fig.width and fig.height params.
I'm generating a lot of ggplots in an automated fashion (for codebooks of surveys). Some of these plots have very long plot titles (often survey questions) and/or x-axis labels.
library(ggplot2)
qplot(1:10,rnorm(10)) +
ggtitle("this is indeed a very long title but sometimes necessary. this is indeed a very long title but sometimes necessary. this is indeed a very long title but sometimes necessary", subtitle = "the very long title has an even longer subtitle to boot, really much longer than the title. the very long title has an even longer subtitle to boot, really much longer than the title.") +
scale_x_continuous(breaks = 1:10, labels = paste("Option", 1:10))
Is there a way to prevent these texts from being clipped (by wrapping or shrinking or rotating them)? A way that can be automated and works for variable-width fonts? Similar questions exist, but address the old version of ggplot2, manual solutions, or facets (which seem more complicated, but there label_wrap_gen seems to handle things well, so I thought a simple solution for titles might exist too).
I control and know the plot width and height before doing the plot (via knitr chunk settings).
I know I can wrap text using \n or strwrap, but there I have to choose the cut points manually and doing so for variable-width fonts often leaves empty space.
Is there any way to annotate a ggplot with three lines one on top of the other, while keeping the text sizes the same across the three lines?
I am almost there but the text sizes are different in the third line, it looks like the bgroup is only using the first two lines and I cannot get this right...
I am adding the text using to "atop" applications from "?plotmath", which works fine but the text in the third line comes out in a different size compared to the other two lines...
library(ggplot2)
line1 = "xxx data1"
line2 = "yyy data2"
line3 = "zzz data3"
df=data.frame(x=rep(1:8, 3), y=c(0,1,3,4,5,6,7,8, 8,7,6,3,2,1,3,4, 0,2,4,5,6,7,8,9), variable=c("x", "x","x","x","x","x","x","x","y","y","y","y","y","y","y","y","z","z","z","z","z","z","z","z"))
p <- ggplot(df) + theme_bw() + geom_point(aes(x=x,y=y, color=variable)) + geom_line(aes(x=x,y=y, color=variable)) +
geom_text(x=max(df$x), y = max(df$y), label = paste('bgroup("{", atop(atop("',line1,'","',line2,'"),"', line3,'"), "}")',sep=''), size=3.5,parse=TRUE)
I thought I was getting all the three lines within the bgroup, but I cannot get the paste right. If there is anything I can try please advise. Thanks very much!
To perfectly center everything (which \n will not do), keep every piece of text the same size whatever the number of lines and at the same time being able to adjust the interlinear space, use this instead:
xlab(expression(atop(textstyle("whateverline1"),atop(textstyle("whateverline2"),atop(scriptscriptstyle(""),textstyle("whateverline3"))))))
Then use labeller=label_parsed
This also works for facet_grid, title and ylab
Note the atop and textstyle to position the text whilst keeping it all the same size and the scriptscriptstyle("") to control spacing between lines. You can also use varied relative sizes of text using scriptstyle or scriptscriptstyle depending on your needs and of course use element_text(size=whatevernumber) in the theme section
If I use \n with labs(title="whatever \n comes after this") I end up with quite a big space between the lines. Is there a way to influence it? (I mean except font-size of the title itself).
you can do something like this ( option lineheight to modify line spacing)
p <- qplot(mpg, wt, data = mtcars)
p <- p + ggtitle("whatever \n comes after this") +
theme(plot.title = element_text(lineheight=.1))
p
To perfectly center everything (which \n will not do in several cases), keep every piece of text the same size or being able to relatively adjust it if there are more than 2 lines (which is useful in some cases) and at the same time being able to adjust the interlinear space, use this instead:
labs(title=expression(atop(textstyle("whateverline1"),atop(textstyle("whateverline2"),atop(scriptscriptstyle(""),textstyle("whateverline3"))))))
Then use labeller=label_parsed
This also works for facet_grid, xlab and ylab
Note the atop and textstyle to position the text whilst keeping it all the same size and the scriptscriptstyle("") to control spacing between lines. You can also use varied relative sizes of text using scriptstyle or scriptscriptstyle depending on your needs