Can anybody tell me how can I use scientific notation in my plot axis THIS WAY with ggplot?
I would like to write the exponential part only in the corners, as you can see in the picture (that plot was made with matplotlib).
Best I can come up with is to use the annotate() function and disabling coord clipping to place text outside the panel bounds. You may have to play a bit with the exact spacing and the expressions will throw warnings.
library(ggplot2)
df <- data.frame(
x = 1:10,
y = 10:1
)
ggplot(df, aes(x, y)) +
geom_point() +
annotate("text", -Inf, Inf, label = expression(""%*%10^1),
hjust = 0, vjust = -1) +
annotate("text", Inf, -Inf, label = expression(""%*%10^-3),
hjust = 1, vjust = 2) +
coord_cartesian(clip = "off") +
theme(plot.margin = margin(t = 30, b = 10, l = 10, r = 10))
#> Warning in is.na(x): is.na() applied to non-(list or vector) of type
#> 'expression'
#> Warning in is.na(x): is.na() applied to non-(list or vector) of type
#> 'expression'
Created on 2020-09-11 by the reprex package (v0.3.0)
Related
i want to insert a text into my ggplot chart. The text got a subscript and a supersubscript like X[X} = 1,00*Y R^2 = 0,90. For that i used the funktion paste(expression()) into annotate(label=()).
In the graphics pane the whole plot looks fine, like i needed. But if i want to save the plot into a svg using the svg.save function the plot missing the Axis and the annotate Text.
Without annotate the whole svg is fine. So i guess, the soloution is fixing the paste(expression()) function. But i didnt found a solution for that.
Data <- read.csv2("Data.csv", header = TRUE, sep = ";", dec = ",")
Data$ï..Date <- as.Date(Data$ï..Date, format = "%d.%m.%Y")
Gesamt_Plot1 <- ggplot() +
geom_point(aes(X$EC,Y$BC), show.legend = FALSE, shape = 1, size = 1.5, na.rm = TRUE)+
geom_abline(linetype = "dashed")+
geom_segment(aes(x = 0.19,xend = 5.49, y = G1_slp*0.19, yend = G1_slp*5.49), color = "black", size = 1.2, na.rm = TRUE)+
annotate(geom="text", x = 4, y=6.4, parse = T, label=paste(expression(EBC~"="~"0,92*"*EC[TOR]~~R²~"="~"0,89")), color="black")+
annotate(geom="text", x=0.1, y=7, label="a)", color="black")+
labs(colour = "", x=expression(EC[TOR]~"in"~mu*g~m^-3), y=expression(EBC~"in"~mu*g~m^-3))+
theme_bw()+
theme(axis.text.y=element_text(size = 12), axis.text.x = element_text(size = 12),
axis.title = element_text(size = 12), legend.position = "bottom", panel.grid.minor = element_blank())+
scale_x_continuous(limit = c(0,7),
breaks = c(0, 1, 2, 3, 4, 5, 6, 7)
)+
scale_y_continuous(limit = c(0,7),
breaks = c(0, 1, 2, 3, 4, 5, 6, 7)
)
https://i.stack.imgur.com/9axhZ.png
Using R Version 4.0.5 and ggplot v3.3.3.
Not sure I can reproduce your problem, but I think you should not be using paste(expression(..)), just use expression(..). (Incidentally, I changed from your R² to R^2 in the expression; I'm not certain if it's a UTF problem in my emacs/ess or not. Try it both ways if you prefer.)
ggplot(mtcars, aes(mpg, disp)) +
geom_point() +
annotate(geom="text", x=20, y=60,
label=expression(EBC~"="~"0,92*"*EC[TOR]~~R^2~"="~"0,89"))
# Warning in is.na(x) :
# is.na() applied to non-(list or vector) of type 'expression'
In the R graphics pane, I see
Saving to svg:
ggsave(filename="mt.svg")
# Warning in is.na(x) :
# is.na() applied to non-(list or vector) of type 'expression'
which then shows
Note: due to a long-standing ... bug/feature (?) in ggplot2, it warns about expressions. Granted, it's just a warning (and it plots fine), so it can be ignored. See Why does ggplot annotate throw this warning: In is.na(x) : is.na() applied to non-(list or vector) of type 'expression'. Another method is this:
ggplot(mtcars, aes(mpg, disp)) +
geom_point() +
annotate(geom="text", x=20, y=60,
label=list('EBC~"="~"0,92*"*EC[TOR]~~R^2~"="~"0,89"'),
parse=TRUE) +
labs(colour = "", x=expression(EC[TOR]~"in"~mu*g~m^-3), y=expression(EBC~"in"~mu*g~m^-3)) +
theme_bw()
(using list('...') instead of expression(...), and adding parse=TRUE). This produces the same effect.
so I've had this question for quite a while now and I have not found a solution to this. Whenever I want to label a parameter of interest, such as central tendencies (mean, median etc.), for example, I create a vertical and/or horizontal line and use annotate for the labeling. However, I have not been able to use LaTeX and non-hardcoded values concurrently. A MRE is shown below:
data <- data.frame(stat = rnorm(1000))
plot <-
ggplot(data, aes(x = stat)) +
geom_histogram(aes(y=..density..), fill="aquamarine", color="black") +
geom_density(color="black", size=1) +
geom_vline(xintercept = 0, color = "blue", linetype="dashed", size = 1) +
annotate("text", x=-0.2, y=0.2,
label=paste0("Mean = ", round(mean(data$stat), 4)),
angle=90, size=7, color="black")
plot
See figure here: https://i.stack.imgur.com/QzojQ.png
In the example above, I generate some random normal data, save it to a dataframe and plot it. I add a dashed vertical line corresponding to the mean of the data and then label it via annotate. Note, however, that I explicitly write Mean in the label since the LaTeX operators don't work and random letters are not ideal for me.
A solution I found is by using expression instead of paste0 when labeling as shown below:
data <- data.frame(stat = rnorm(1000))
plot <-
ggplot(data, aes(x = stat)) +
geom_histogram(aes(y=..density..), fill="aquamarine", color="black") +
geom_density(color="black", size=1) +
geom_vline(xintercept = 0, color = "blue", linetype="dashed", size = 1) +
annotate("text", x=-0.25, y=0.2, label = expression(mu ~ "= -0.0403"),
angle=90, size = 7, color = "black")
plot
See figure here: https://i.stack.imgur.com/rnW5i.png
This allows us to get the LaTeX characters, such as $\mu$ in our case, to show in the plot. But now the downside is that I have to hardcode the mean value in the expression field. This is not ideal and I don't want to do this. I want to be able to do something as follows but this doesn't work:
annotate("text", x=-0.25, y=0.2,
label = expression(mu ~ round(mean(data$stat), 4)),
angle=90, size = 7, color = "black")
I have not been able to find a solution to this so any help is greatly appreciated.
One option to fix that would be to create your expression as a character string instead of using expression and add parse=TRUE to annotate:
library(ggplot2)
set.seed(123)
data <- data.frame(stat = rnorm(1000))
ggplot(data, aes(x = stat)) +
geom_histogram(aes(y = after_stat(density)), fill = "aquamarine", color = "black") +
geom_density(color = "black", size = 1) +
geom_vline(xintercept = 0, color = "blue", linetype = "dashed", size = 1) +
annotate("text",
x = -0.2, y = 0.2,
label = paste0("mu ==", round(mean(data$stat), 4)),
angle = 90, size = 7, color = "black", parse = TRUE
)
#> Warning: Using `size` aesthetic for lines was deprecated in ggplot2 3.4.0.
#> ℹ Please use `linewidth` instead.
#> `stat_bin()` using `bins = 30`. Pick better value with `binwidth`.
Say I have the below df
library(ggplot2)
library(data.table)
# dummy data
df <- data.table(revenue = rnorm(1e4, mean = 100, sd = 1)); df
revenue
1: 100.01769
2: 98.31862
3: 99.78464
4: 100.17670
5: 99.31678
---
9996: 99.47635
9997: 98.27383
9998: 99.48378
9999: 100.06227
10000: 99.13972
and that I plot a histogram with a vline denoting the mean
# mean of x axis
x <- df[, mean(revenue)]
# plot
ggplot(df, aes(x = revenue)) +
geom_histogram(aes(y = (..count..) / sum(..count..))) + # turn count into %
geom_vline(aes(xintercept = x), col = 'red', size = 1)
The above is fine. However, when trying to add a label showing the mean, I am unsure what to enter for y in geom_label(aes(x = x, y = ?)...:
# plot
ggplot(df, aes(x = revenue)) +
geom_histogram(aes(y = (..count..) / sum(..count..))) + # turn count into %
geom_vline(aes(xintercept = x), col = 'red', size = 1) +
geom_label(aes(x = x, y = ?)
, label = x
)
I have tried small numbers such as 0.025 (after looking at the density from the previous plot) but then R gets stuck and creating the plot and never finishes. Say, I'd like to position the numeric label at where y axis = 0, then what value should I put into y = ?
Thank you
Remove aes() from geom_label, you are plotting constants, not a data.table variables . To plot where the y axis is zero, well, make y = 0.
Use hjust and vjust to position the label relative to (the constants) x, y. From the documentation:
Alignment
You can modify text alignment with the vjust and hjust aesthetics. These can either be a number between 0 (right/bottom) and 1 (top/left) or a character ("left", "middle", "right", "bottom", "center", "top"). There are two special alignments: "inward" and "outward". Inward always aligns text towards the center, and outward aligns it away from the center.
And it does take time. Once again from the documentation, my emphasis:
geom_label()
Currently geom_label() does not support the check_overlap argument or the angle aesthetic. Also, it is considerably slower than geom_text(). The fill aesthetic controls the background colour of the label.
library(ggplot2)
#library(data.table)
# dummy data
df <- data.frame(revenue = rnorm(1e4, mean = 100, sd = 1))
xbar <- mean(df$revenue)
# plot
ggplot(df, aes(x = revenue)) +
geom_histogram(aes(y = (..count..) / sum(..count..)), bins = 30) +
geom_vline(aes(xintercept = xbar), col = 'red', size = 1) +
geom_label(x = xbar, y = 0, label = round(xbar, 2),
hjust = -0.5, vjust = 1,
fill = "white", color = "black")
Created on 2022-08-31 by the reprex package (v2.0.1)
I am using the following code to try to preserve geom elements that are out of bounds of the plotting area but it still seems to be clipping them beyond a certain distance above the plotting area.
g <- ggplot(iris, aes(x = Species, y = Petal.Length)) +
stat_summary(geom = 'bar', fun.y = mean) +
geom_point() +
scale_y_continuous(limits = c(0,8), expand = c(0,0), oob = function(x, ...) x) +
geom_text(label = 'obText', aes(x = 2, y = 9)) #+
# theme(plot.margin = unit(c(60,5.5,5.5,5.5), "points"),
# aspect.ratio = 1)
gb <- suppressWarnings(ggplot_build(g))
gt <- ggplot_gtable(gb)
gt$layout$clip[gt$layout$name=="panel"] <- "off"
grid::grid.newpage()
grid::grid.draw(gt)
Any ideas on why this is and how to correct it? If I uncomment the theme argument, I can get close to what I want but this changes the aspect ratio of the plotting area.
Not sure if this is what you're looking for but you can use clip = 'off' option in ggplot 3.0.0 to get the text show up
See also this answer for more information
# install.packages("devtools")
# devtools::install_github("tidyverse/ggplot2")
library(ggplot2)
g <- ggplot(iris, aes(x = Species, y = Petal.Length)) +
stat_summary(geom = 'bar', fun.y = mean) +
geom_point() +
scale_y_continuous(limits = c(0,8), expand = c(0,0), oob = function(x, ...) x) +
geom_text(label = 'obText', aes(x = 2, y = 9), check_overlap = TRUE) +
# this will allow the text outside of the plot panel
coord_cartesian(clip = 'off') +
theme(plot.margin = margin(4, 2, 2, 2, "cm"))
g
Created on 2018-06-28 by the reprex package (v0.2.0.9000).
If you want to see the points, you can change the value of oob =...
oob = function(x, ...) x
oob = squish
oob = censor
squish and censor are part of the scales package.
Note that the mean changes in both cases; squish lowers the value of the points above 6, and censor removes the points above 6.
I usually use infinite values in the position aesthetics of ggplot text objects to make labels appear in the corner of the plot regardless of the data scale. I mainly use this when making multi-panel figures which should have letters in each panel to identify each panel in the figure legend. However, this does not seem to work with log scales if I want the label to appear on the left or bottom, since obviously transforming log(-Inf) returns NaN. Is there an easy fix for this? I could do a long workaround but I was hoping there is something easier. Example is below:
notlogdata <- data.frame(x = 1:3,y = 1:3)
ggplot(notlogdata, aes(x = x,y = y)) +
geom_point() +
geom_text(data = data.frame(x = -Inf, y = Inf, l = 'a'), aes(label = l), hjust = -0.5, vjust = 1)
logdata <- data.frame(x = 10^(1:3), y = 10^(1:3))
ggplot(logdata, aes(x = x,y = y)) +
geom_point() +
geom_text(data = data.frame(x = -Inf, y = Inf, l = 'a'), aes(label = l), hjust = -0.5, vjust = 1) +
scale_x_log10() +
scale_y_log10()
First plot with untransformed axes appears fine:
The second plot does not have a label and returns the warning:
Warning messages:
1: In self$trans$transform(x) : NaNs produced
2: Removed 1 rows containing missing values (geom_text).
annotation_custom(gTree(children=gList(textGrob("a", hjust=0,x=0,vjust=1,y=1))))
You can take a log of Inf --- log(Inf) is Inf. The issue is you can't take a log of a negative like -Inf. But log(0) is -Inf, so if you set x = 0 it will work as expected.
ggplot(logdata, aes(x = x,y = y)) +
geom_point() +
geom_text(
data = data.frame(x = 0, y = Inf, l = 'a'),
aes(label = l), hjust = -0.5, vjust = 1
) +
scale_x_log10() +
scale_y_log10()
It does not appear to be possible to use negative positioning aesthetics, including -Inf, on a log-transformed axis. Here is a solution using cowplot as suggested by zx8754
library(cowplot)
notlogdata <- data.frame(x = 1:3,y = 1:3)
notlogplot <- ggplot(notlogdata, aes(x = x,y = y)) +
geom_point()
logdata <- data.frame(x = 10^(1:3), y = 10^(1:3))
logplot <- ggplot(logdata, aes(x = x,y = y)) +
geom_point() +
scale_x_log10() +
scale_y_log10()
plot_grid(notlogplot, logplot, labels=c('a','b'), hjust=-8)
This outputs the plot below: