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...)
Related
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.
I want to put some labels into a boxplot, to show significance values. My favorite would be the position left bottom. I tried to do it with legend, but had the problem that I don't have any symbols to show and couldn't find anything to show the legend without symbols. I found this, but thought it's way too complicated. There should exist an easier solution.
If it's possible I would prefer to use the base R functionality and no plugin.
So this is how it looks like now and I want the labels (in rows) in the bottom left corner without the gap in the beginning.
Maybe the legend command isn't the command I'm looking for?
One way to do this is to write the text directly using the text function.
Since you do not provide your data, I will illustrate with some built-in data, but you will need to adjust the placement for your specific plot.
boxplot(Sepal.Width ~ Species, data=iris, ylim=c(1,5))
text(0.45,0.95, "1960-2002**\n2002-2012**\nt-test verb.", adj=c(0,0))
The adj=c(0,0) part is to left-justify the text.
If you want the box around the text, add:
rect(0,0,1.2,1.6)
You also can do this with legend and get rid of the gap by specifying the x,y coordinates of the legend. Once again, you will need to adjust for your plot.
boxplot(Sepal.Width ~ Species, data=iris, ylim=c(1,5))
legend(0.23, 1.65, c("1960-2002**", "2002-2012**", "t-test verb."))
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
I have a plot with no x-label. Instead, I want to just have two text boxes on the bottom left (saying "Negative) and bottom right (saying "Positive").
I have my plot object (p), but have tried different ways to achieve what I want, failing each time. For instance, this does not create the text box in the bottom left of the plot.
p + legend.title("Negative") + legend.position(c("bottom","left"))
Any advice is appreciated!
I think you are looking for the annotate function with which you can add text to a plot:
p + annotate("text", x = x-position-value, y = y-position-value, label = "Negative")
You can also add rectangles, lines and pointranges with this function. For some further details about how to use this function, see the official documentation