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
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 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...)
There is either a bug in ggplot or a bug in my brain.
The double green bar at height 27 should be a single line. It is defined by two x values and a single y value twice:
Even worse, if I expand the image to full screen more of these fly apart
Does anyone have any insight into this? Thanks.
ggplot() +
geom_line(data=plotData,
aes(x=x,y=y,group=interaction(y,type),color=color,
size=lineSize,linetype=lineType)) +
scale_color_manual(values=group.colors) +
ggtitle('EScells') +
xlab('chr2') +
ylab('')
Not surprisingly, the bug was in my brain. ggplot was treating the lines in question as dashed lines. Some of these dashed lines only became visible as dashes in the larger sized image.
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
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