I would like to put the following text behind the ggplot chart
And I thought it should be very easy to achieve. Unfortunately, all my attempts ended in a complete failure.
I have already read over a dozen posts on this forum that dealt with this topic. I have already made several dozen attempts and still do not manage to get the effect I expect.
By the way, I noticed a rather strange treatment of unicode symbols. Please compare the title and subtitle from the chart below.
library(tidyverse)
ggplot()+
labs(
title = expression("\u00AE \u00A9, \u00A2, \u00BC, \u00BD, \u00BE, \u00A5, \u00D8, \u00F8"),
subtitle = "\u00AE \u00A9, \u00A2, \u00BC, \u00BD, \u00BE, \u00A5, \u00D8, \u00F8"
)+
annotate(geom="text", label="\u00D828.15^{+0.15}", x=0, y=0.08,parse = TRUE, size=5)+
annotate(geom="text", label="\u00D8", x=0, y=0, size=5)+
annotate(geom="text", label="28.15^{+0.15}", x=0.03, y=0.001,parse = TRUE, size=5)+
xlim(c(-0.1, 0.1))+
ylim(c(-0.02, 0.1))+
theme_void()
Why do some unicode symbols lose some of their graphics when placed inside an expression function or when I use the parse option? This happens with the symbols ¢, ¥, ¼, ½, ¾, Ø. In my case, I particularly care about the symbol Ø. I finally got the effect on the track chart (annotation at the bottom of the chart) was created from the tedious setting of two annotations next to each other. However, it completely falls apart as soon as I change the size of the chart.
Does anyone know how this can be solved?
Thank you very much for your quick reply. Unfortunately, it still doesn't work for me! :-(
library(latex2exp)
library(ggplot2)
label <- TeX("$Ø28.15^{+0.15}$")
qplot(1, "A") +
annotate(geom = "text", label = label, x = 1, y = 1.1, size = 10) +
xlab(label)
You can use LaTeX syntax within a math ($) environment to auto-generate the plotmath expression:
library(latex2exp)
library(ggplot2)
label <- TeX("$Ø28.15^{+0.15}$")
label
#> expression(`$Ø28.15^{+0.15}$` = paste("", "Ø28", ".", "15",
#> phantom()^{
#> paste("+0", ".", "15")
#> }, ""))
qplot(1, "A") +
annotate(geom = "text", label = label, x = 1, y = 1.1, size = 10) +
xlab(label)
#> Warning in is.na(x): is.na() applied to non-(list or vector) of type
#> 'expression'
Created on 2021-10-18 by the reprex package (v2.0.1)
I know how to modify this solution above, maybe not so cute, but works everywhere
library(ggplot2)
label <- "\u00D828.15\U207A\u2070\U00B7\U00B9\u2075"
qplot(1, "A") +
annotate(geom = "text", label = label, x = 1, y = 1.1, size = 10) +
xlab(label)
Related
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)
I'm designing some graphs within a function with ggPlot2 geom_text.
It is a sequence of five graphs and, in each one, I want to place my label (my text) in the top right position.
The problem is that I will constantly change my N and Y values (according to and input interval). X and Y coordinates will change, and even be out of scale.
So how do I make the label placement fixed, let's say in the top right, in my graph?
Here's my code
parte.mac <- subset(dados, subset = (dados$Especie == 'C.macelaria' & dados$Temp >= minima & dados$Temp <= maxima))
mac <- qplot(Temp, Tempo, data = parte.mac, color = Especie, main = 'C.macelaria', geom = c("point", "line"), add = T) +
stat_smooth(method = 'lm', level = 0.99, alpha = 0.5, aes(group=1), color = 'blue') +
geom_text(x = maxima, y = mean(range(dados$Tempo)), label = mac.sm, parse = TRUE)
Please, help
Echoing the comment by #jazzuro, could you provide us with (your) reproducible data by running (don't send anything confidential!)
dput(parte.mac)
and pasting that with your question.
In the absence of your exact data, I'll echo #baptiste with a simple example using the "faithful" data file of the Old Faithful geyser eruptions:
data(faithful)
head(faithful)
p <- qplot(x=eruptions, y=waiting, data=faithful)
and then here is one example of an annotation:
p + annotate("text", x=3, y=40, label="Group 1") + annotate("text", x=4.5, y=60, label="Group 2")
Below is a second example, using arguments such as "min" and "max" for placement of the annotations:
p + annotate("text", x=min(faithful$eruptions), y=min(faithful$waiting), label="Group 1") + annotate("text", x=max(faithful$eruptions), y=max(faithful$waiting), label="Group 2")
If this doesn't help, remember to dput your data and paste into your question.
Is it possible, in ggplot2, to colorize labels for a group of points?
I would like to color some of the left-hand-side text labels in the plot below to show the swing states in red colour, in addition to the red marker shown in the plot itself:
The code (with data) is here. -- edited to reflect answer
I know how to colour all labels (here too), but that's not what I need here.
Ideally, I'd also like to improve the legend but am unsure exactly how.
The plot is far from perfect, so additional suggestions are very welcome. There are far better graphs out there if anyone's interested (but I'm not good enough to code them).
Colors of labels (axis texts) are set by argument element_text= in function theme(). You can set different colors for each label. As there is a column Swing with levels, it can be used to set colors.
dw_plot + theme(axis.text.y = element_text(colour = ifelse(dw_data$Swing=="Swing State","red","grey")))
The answers stated above work as of today; however, they throw warning which discourages from using the suggested method with ifelse inside element_text(). The reason why vectorisation in element_text() is not documented in ggplot2 is because it is not supported feature (it works due to a chance). Please see the following issue on GitHub where this specific problem was discussed.
The answers provided above will result in the following warning:
# Warning message:
# Vectorized input to `element_text()` is not officially supported.
# Results may be unexpected or may change in future versions of ggplot2.
The following code illustrates the point (using slightly updated example provided by SlowLearner - original data are not available) and shows my solution that supports the vectorisation using the ggtext package and element_markdown().
library(ggplot2); packageVersion("ggplot2")
# ‘3.3.0’
library(ggtext); packageVersion("ggtext") #; install.packages("ggtext") # https://github.com/wilkelab/ggtext
# ‘0.1.0’
set.seed(1234)
df <- data.frame(state = paste("State_", LETTERS, sep = ""),
margin = runif(26, -50, 50),
swing = rep(c("no", "yes", "no"), times = c(10, 6, 10)))
mycolours <- c("yes" = "red", "no" = "black")
ggplot(data = df, aes(x = margin, y = state)) +
geom_point(size = 5, aes(colour = swing)) +
scale_color_manual("Swing", values = mycolours) +
theme(
# The following line uses vectorisation (such as rep or ifelse).
# This is not officially supported. Works by a chance and gives impression of a feature.
axis.text.y = element_text(colour = rep(c("black", "red", "black"), times = c(10, 6, 10)))
)
# Throws the following warning:
# Warning message:
# Vectorized input to `element_text()` is not officially supported.
# Results may be unexpected or may change in future versions of ggplot2.
# The following code uses ggtext method # element_markdown(),
# This is how this question should be solved because the vectorisation method may not work in the future inside element_text().
ggplot(data = df, aes(x = margin, y = state)) +
geom_point(size = 5, aes(colour = swing)) +
scale_color_manual("Swing", values = mycolours) +
theme(axis.text.y = element_markdown(colour = rep(c("black", "red", "black"), times = c(10, 6, 10))))
# No warning occurs. This will also correctly calculate other aesthetic such as size.
Other answer already accepted, but just as a visual example... For more complex schemes you can simply add a column to the data frame with the required colours and reference that instead of using 'red' and 'black' as per below.
library(ggplot2)
set.seed(1234)
x <- data.frame(state = paste("State_", LETTERS, sep = ""),
margin = runif(26, -50, 50), swing = rep("no", 26))
x[c(10:15), 'swing'] <- "yes"
mycolours <- c("yes" = 'red', "no" = "black")
ggplot(data = x, aes(x = margin, y = state)) +
geom_point(size = 5, aes(colour = swing)) +
scale_color_manual("Swing", values = mycolours) +
theme(axis.text.y = element_text(colour =
ifelse(x$swing == 'yes', 'red', 'black'))) +
theme()
I'd like to write an axis label over two lines with an expression() statement. However, plotmath and expression won't allow this (e.g. subscripted text appears on the far right). I found this discussion circa 2005 of a similar issue but the work around that they offer doesn't translate to my application in ggplot2. A recent question addressed a different permutation of multi-line expression statements, but again the work around provided doesn't apply here.
Example:
p <- ggplot(mtcars,aes(x=wt,y=mpg))+
geom_point()+
xlab(expression(paste("A long string of text goes here just for the purpose \n of illustrating my point Weight "[reported])))
try(ggsave(plot=p,filename=<some file>,height=4,width=6))
yields an image where subscript "reported" is kicked out to the right when I'd like it to sit next to the previous word.
I think this is a bug. (Or a consequence of the fact that "multi-line expressions are not supported", as stated in the conversation you linked to).
The workaround that Gavin Simpson alluded to is:
#For convenience redefine p as the unlabeled plot
p <- ggplot(mtcars,aes(x=wt,y=mpg))+geom_point()
#Use atop to fake a line break
p + xlab(expression(atop("A long string of text for the purpose", paste("of illustrating my point" [reported]))))
It is possible to use true line breaks with subscripts. In the short example below, which has the same form as your example, the subscript is correctly placed adjacent to the rest of the text but the two lines of text are not centered correctly:
p + xlab(expression(paste("line1 \n line2 a" [b])))
I think that in both cases, the subscript is placed wrong when the upper line of text is longer than the lower line of text. Compare
p + xlab(expression(paste("abc \n abcd" [reported])))
p + xlab(expression(paste("abc \n ab" [reported])))
The subscript always ends up aligned just to the right of the right end of the upper line.
p + xlab(expression(paste("abcdefghijklmnop \n ab" [reported])))
1) Solution with cowplot::draw_label()
One could also use the annotation function draw_label() from the package cowplot (suggested in this discussion). We could call cowplot::draw_label() as many lines of text we have. When cowplot::draw_label() is used in combination with cowplot::ggdraw(), it can annotate anywhere on the canvas/sheet with the coordinates ranging from 0 to 1 (relative to the entire canvas).
One needs to tweak the annotation position and make enough space for the custom axis title.
Note that the cowplot package currently alters the default ggplot theme, therefore, if needed, use theme_set() after loading the package as mentioned here.
Note also that the function cowplot::draw_label() uses ggplot2::annotation_custom() under the hood. I'll mention more about this in the second part below.
library(ggplot2)
library(cowplot)
#>
#> Attaching package: 'cowplot'
#> The following object is masked from 'package:ggplot2':
#>
#> ggsave
# If needed, revert to default theme (cowplot modifies the theme);
# theme_set(theme_grey())
p <- ggplot(mtcars, aes(x = wt, y = mpg)) + geom_point()
# Make enough space for the custom two lines axis title
p <- p +
xlab("") + # empty label
# Tweak the margins (push the label down by forcing a wider top margin)
theme(axis.title.x = element_text(size = 10, # also adjust text size if needed
margin = margin(t = 10, r = 0, b = 0, l = 0,
unit = "mm")))
# The two lines we wish on the plot
line_1 <- "A long string of text for the purpose"
line_2 <- expression(paste("of illustrating my point" [reported]))
# Or avoid paste() (is not actually needed)
# line_2 <- expression("of illustrating my point" [reported])
# Call cowplot::draw_label two times to plot two lines of text
ggdraw(p) +
draw_label(line_1, x = 0.55, y = 0.075) + # use relative coordinates for positioning
draw_label(line_2, x = 0.55, y = 0.025)
Note that, cowplot::draw_label() can also be used in combination with setting the clipping off, coord_cartesian(clip = "off"), which allows plotting anywhere on the canvas. This time we do not use the relative coordinates anymore, but the ones from the plot/data (the absolute coordinates):
# Other two expressions
line_1b <- expression(bolditalic('First line'))
line_2b <- expression(integral(f(x)*dx, a, b))
p + coord_cartesian(clip = "off") + # allows plotting anywhere on the canvas
draw_label(line_1b, x = 3.5, y = 8.2) + # use absolute coordinates for positioning
draw_label(line_2b, x = 3.5, y = 6)
Created on 2019-01-14 by the reprex package (v0.2.1)
2) Solution with ggplot2::annotation_custom()
As mentioned, cowplot::draw_label() is a wrapper of ggplot2::annotation_custom(). So, instead of cowplot::draw_label(), we could use directly ggplot2::annotation_custom() in combination with setting the clipping off - coord_cartesian(clip = "off"), which became available with merging this pull request.
However, this approach is more verbose, with more coordinate arguments and we need to employ grid::textGrob().
# Some other two lines we wish on the plot as OX axis title
line_1c <- expression("Various fonts:" ~ bolditalic("bolditalic") ~ bold("bold") ~ italic("italic"))
line_2c <- expression("this" ~~ sqrt(x, y) ~~ "or this" ~~ sum(x[i], i==1, n) ~~ "math expression")
# the ~~ ads a bit more space than ~ between the expression's components
p + coord_cartesian(clip = "off") +
annotation_custom(grid::textGrob(line_1c), xmin = 3.5, xmax = 3.5, ymin = 7.3, ymax = 7.3) +
annotation_custom(grid::textGrob(line_2c), xmin = 3.5, xmax = 3.5, ymin = 5.5, ymax = 5.5)
Created on 2019-01-14 by the reprex package (v0.2.1)
The package ggtext offers a different option, by allowing for HTML tags to format/customise labels and text.
library(ggtext)
ggplot(mtcars, aes(wt, mpg)) +
geom_point() +
xlab("A long string of text goes here just for the purpose<br>of illustrating my point Weight<sub>reported</sub>") +
theme(axis.title.x = element_markdown())
You could use this trick,
library(gridExtra)
library(grid)
element_custom <- function() {
structure(list(), class = c("element_custom", "element_text"))
}
element_grob.element_custom <- function(element, label="", ...) {
mytheme <- ttheme_minimal(core = list(fg_params = list(parse=TRUE,
hjust=0, x=0.1)))
disect <- strsplit(label, "\\n")[[1]]
tableGrob(as.matrix(disect), theme=mytheme)
}
# default method is unreliable
heightDetails.gtable <- function(x) sum(x$heights)
ggplot(iris, aes(Sepal.Length, Sepal.Width)) +
geom_line() +
labs(x= "First~line \n italic('and a second') \n integral(f(x)*dx, a, b)")+
(theme_grey() %+replace% theme(axis.title.x = element_custom()))
Can I adjust the point size, alpha, font, and axis ticks in a plotmatrix?
Here is an example:
library(ggplot2)
plotmatrix(iris)
How can I:
make the points twice as big
set alpha = 0.5
have no more than 5 ticks on each axis
set font to 1/2 size?
I have fiddled with the mapping = aes() argument to plotmatrix as well as opts() and adding layers such as + geom_point(alpha = 0.5, size = 14), but none of these seem to do anything. I have hacked a bit of a fix to the size by writing to a large pdf (pdf(file = "foo.pdf", height = 10, width = 10)), but this provides only a limited amount of control.
Pretty much all of the ggplot2 scatterplot matrix options are still fairly new and can be a bit experimental.
But the facilities in GGally do allows you to construct this kind of plot manually, though:
custom_iris <- ggpairs(iris,upper = "blank",lower = "blank",
title = "Custom Example")
p1 <- ggplot(iris,aes(x = Sepal.Length,y = Sepal.Width)) +
geom_point(size = 1,alpha = 0.3)
p2 <- ggplot(iris,aes(x = Sepal.Width,y = Sepal.Length)) +
geom_point()
custom_iris <- putPlot(custom_iris,p1,2,1)
custom_iris <- putPlot(custom_iris,p2,3,2)
custom_iris
I did that simply by directly following the last example in ?ggpairs.