What's the expression for partial derivative in ggplot()? - r

Is it possible to get the partial derivative symbol via expression() in ggplot2, e.g. to be used in axis labels?
I am talking about this symbol, often also refered to as 'del' or 'curly d': https://en.wikipedia.org/wiki/%E2%88%82
It has unicode number U+2202, but when I try to include it in ggplot, it fails:
a <- b <- rnorm(100)
plot.df <- data.frame(a,b)
ggplot(plot.df,aes(a,b)) +
geom_point() +
xlab(expression('\u2202'))
For comparison, using e.g. the plus/minus sign with unicode number U+00B1 works fine:
ggplot(plot.df,aes(a,b)) +
geom_point() +
xlab(expression('\u00b1'))

you can achieve this using the keyword partialdiff. using your example:
ggplot(plot.df,aes(a,b)) +
geom_point() +
xlab(expression(paste(partialdiff,"y","/",partialdiff,"x")))
This link provides some good reference on the matter.
Depending how far you want to go. You can eventually use TikzDevice library to save the plot directly as a tex.file. It might take longer to compile the graph but I find it more flexible.
library(tikzDevice)
tikz("/tmp/test.tex",standAlone = TRUE)
ggplot(plot.df,aes(a,b)) +
geom_point() +
xlab("$\\frac{\\partial{y}}{\\partial{x}}$")
dev.off()

With the ggtext package you can use HTML entities:
library(ggplot2)
library(ggtext)
a <- b <- rnorm(100)
plot.df <- data.frame(a,b)
ggplot(plot.df, aes(a,b)) +
geom_point() +
xlab("∂") +
theme(axis.title.x = element_markdown(size = 20))

Related

Convert ggplot to greyscale with stat_summary

I have an R package as a back-end engine for a GUI (JASP). I want to be able to have people convert their images to greyscale (for publication printing). For most plots, I can use scale_colour_grey(), but that doesn't work when colors are specified within stats_summary. For example:
# simulate data
set.seed(1212)
y = rnorm(100)
g = sample(c("a", "b"), 100, T)
d = data.frame(y=y, g=g)
### create ggplot
plot = ggplot(data=d, aes(x=g, y=y)) +
geom_jitter() +
stat_summary(fun="mean", geom="point", size=3, color="red") +
stat_summary(geom="errorbar", size=3, color="red") +
theme_bw()
### converting to greyscale doesn't work
plot + scale_colour_grey()
After some research, I learned you can dissect the ggplot object then rebuilt it:
### can rebuilt ggplot object, but not ideal
q <- ggplot_build(plot)
q$data[[2]]$colour <- "black"
q$data[[3]]$colour <- "black"
q <- ggplot_gtable(q)
plot = ggplotify::as.ggplot(q)
plot
That works fine, but I try to include as few dependencies in my R packages as possible. Do I really have to resort to another package (ggplotify) in order to modify the color coming from stat_summary?
A few notes: I don't want to have to modify the original stat_summary statement. Let's just pretend that cannot be modified. Also, let's assume I cannot add another package (aside from ggplot2, which is already loaded). Remember, I'm a "guest" in the JASP framework and I don't want to have to add another package to the list of packages they have to store.
You can actually get at the ggplot object before it is built, reach into the layer that has the coloured object and change it. Here's a full reprex:
library(ggplot2)
# simulate data
set.seed(1212)
y = rnorm(100)
g = sample(c("a", "b"), 100, T)
d = data.frame(y=y, g=g)
### create ggplot
p <- ggplot(data=d, aes(x=g, y=y)) +
geom_jitter() +
stat_summary(fun="mean", geom="point", size=3, color="red") +
stat_summary(geom="errorbar", size=3, color="red") +
theme_bw()
p
p$layers[[3]]$aes_params$colour <- "gray50"
p
If you want a more general approach to change a particular geom's colour, you could do something like this function:
recolour_geom <- function(gg_plot, geom, colour = "gray50")
{
ss <- which(sapply(p$layers, function(l) {
paste(gsub("GEOM|GG|PROTO", "", toupper(class(l$geom))),
collapse = "")}) %in% toupper(geom))
if (length(ss) > 0)
{
for (i in ss)
{
p$layers[[i]]$aes_params$colour <- colour
}
}
p
}
Which allows you to do, for example
recolour_geom(p, "errorbar", "blue")
recolour_geom(p, "point", "green")
Be aware though that this changes the ggplot by reference, so p is changed as a side effect of the function.
Created on 2020-08-14 by the reprex package (v0.3.0)

ggplot update and not add a layer

I know there are ways to update settings of a given ggplot graph.
I want to save two files, one with the standard setting as png and another one as pdf but with a different label size.
df <- data.frame(a=c('a;b;c','d;e;f'), b=c('A;B;C','D;E;F'),
x=c(1,2), y=c(2,3))
g <- ggplot(df, aes(x,y)) + geom_point() + geom_text(aes(label=a))
ggsave('test1.png',g)
ggsave('test2.pdf',g + geom_text(aes(label=a), size=10))
Is there a way to remove or update the old geom_text layer and not just add a layer to the graph?
Look into str(g) and update relevant bits, in your case following should work:
g$layers[[2]]$geom_params$size <- 10
One option would be to have a simpler basic object g and then add the layers you need
g <- ggplot(df, aes(x,y)) + geom_point()
ggsave('test1.png', g + geom_text(aes(label=a)))
ggsave('test2.pdf', g + geom_text(aes(label=a), size=10))
You can also put the size argument inside the aes and then use scale_size_manual to get different scales.
g <- ggplot(df, aes(x,y)) +
geom_point() +
geom_text(aes(label=a, size="size"), show_guide = FALSE)
g + scale_size_manual(values=c(size = 10))

comfortable way to use unicode characters in a ggplot graph

Is there a good practice to insert unicode characters in a ggplot title and also save it as pdf?
I am struggling with expression, paste and sprintf to get a nice title...
So, what works is
ggtitle(expression(paste('5', mu, 'g')))
This will print an ugly greek mu. By ugly I mean a different font, but overall, it will be printed as pdf without problems. But the problems start, if you want to have new lines in the title. Or maybe I didn't found a solution for this.
My preferred solution would be to use sprintf with the unicode number, so for example
ggtitle(sprintf('5\u03BCg'))
It shows a nice result on the screen but it is not possible to save as pdf with ggsave. PNG works fine, but I would like to use the pdf save option.
Is there a possibility to plot the unicode characters with ggsave? I read about the cairo_pdf device, but this messes up the fonts and I can not save the plot properly.
Thanks in advance for any help.
EDIT:
Example PDF
I just uploaded an example PDF... So maybe my problem is somewhere else...
Try
library(ggplot2)
p <- ggplot(df, aes(x=date, y=value))
p <- p + geom_line()
p + ggtitle(sprintf('5\u03BCg'))
library(Cairo)
ggsave("newfile.pdf", device=cairo_pdf)
data
set.seed(42)
df <- data.frame(date = 1:10 , value = cumsum(runif(10 , max = 10)) )
Using the emojifont package fixes this issue for me.
library(emojifont)
I am sharing the tricks to have Unicode characters properly displayed on PDF files. I am currently running R-4.0.5 for Windows.
library(ggplot2)
library(gridExtra)
library(grid)
library(png)
#--- The trick to get unicode characters being printed on pdf files:
#--- 1. Create a temporary file, say "temp.png"
#--- 2. Create the pdf file using pdf() or cairo_pdf(), say "UnicodeToPDF.pdf"
#--- 3. Combine the use of grid.arrange (from gridExtra), rasterGrob (from grid), and readPNG (from png) to insert the
# temp.png file into the UnicodeToPDF.pdf file
test.plot = ggplot() +
geom_point(data = data.frame(x=1, y=1), aes(x,y), shape = "\u2191", size=3.5) +
geom_point(data = data.frame(x=2, y=2), aes(x,y), shape = "\u2020", size=3.5) +
geom_point(data = data.frame(x=1.2, y=1.2), aes(x,y), shape = -10122, size=3.5, color="#FF7F00") +
geom_point(data = data.frame(x=1.4, y=1.4), aes(x,y), shape = -129322, size=3.5, color="#FB9A99") +
geom_point(data = data.frame(x=1.7, y=1.7), aes(x,y), shape = -128515, size=5, color="#1F78B4") +
ggtitle(sprintf('5\u03BCg'))
ggsave("temp.png", plot = test.plot, width = 80, height = 80, units = "mm")
#--- Refer to http://xahlee.info/comp/unicode_index.html to see more unicode character integers
pdf("UnicodeToPDF.pdf")
grid.arrange(
rasterGrob(
readPNG(
"temp.png",
native=F
)
)
)
dev.off()
file.remove("temp.png")

Linear discriminant analysis plot using ggplot2

How can I add the sample ID (row number) as labels to each point in this LDA plot using ggplot2?
Thanks
Script:
require(MASS)
require(ggplot2)
data(iris)
irisLda <- lda(iris[,-5],iris[,5])
irisLda <- lda(Species~.,data=iris)
plot(irisLda)
irisProjection <- cbind(scale(as.matrix(iris[,-5]),scale=FALSE) %*% irisLda$scaling,iris[,5,drop=FALSE])
p <- ggplot(data=irisProjection,aes(x=LD1,y=LD2,col=Species))
p + geom_point()
You simply need to use geom_text:
irisProjection$row_num = 1:nrow(irisProjection)
p <- ggplot(data=irisProjection, aes(x=LD1,y=LD2,col=Species)) +
geom_point() + geom_text(aes(label = row_num))
print(p)
Maybe you need to play around a bit with hjust and vjust, which are part of geom_text. You also might want to have a look at the directlabels package for smart label placement.

How to get a reversed, log10 scale in ggplot2?

I'd like to make a plot with a reversed, log10 x scale using ggplot2:
require(ggplot2)
df <- data.frame(x=1:10, y=runif(10))
p <- ggplot(data=df, aes(x=x, y=y)) + geom_point()
However, it seems that I can either a log10 scale or a reversed scale:
p + scale_x_reverse() + scale_x_log10()
p + scale_x_reverse()
I guess this is logical, if a layer can only have one scale. And certainly I could hack it by doing the log transform on the dataframe myself, df$xLog <- log10(df$x)
but that solution is a seems contrary to the spirit of ggplot. Is there a way to get this kind of plot without doing data transformations external to the ggplot call?
[See #user236321's answer for a more modern (post April 2022) answer.]
The link that #joran gave in his comment gives the right idea (build your own transform), but is outdated with regard to the new scales package that ggplot2 uses now. Looking at log_trans and reverse_trans in the scales package for guidance and inspiration, a reverselog_trans function can be made:
library("scales")
reverselog_trans <- function(base = exp(1)) {
trans <- function(x) -log(x, base)
inv <- function(x) base^(-x)
trans_new(paste0("reverselog-", format(base)), trans, inv,
log_breaks(base = base),
domain = c(1e-100, Inf))
}
This can be used simply as:
p + scale_x_continuous(trans=reverselog_trans(10))
which gives the plot:
Using a slightly different data set to show that the axis is definitely reversed:
DF <- data.frame(x=1:10, y=1:10)
ggplot(DF, aes(x=x,y=y)) +
geom_point() +
scale_x_continuous(trans=reverselog_trans(10))
ggforce package has trans_reverser() function for this task.
library(ggplot2)
library(ggforce)
p <- ggplot() +
geom_line(aes(x = 1:100, y = 1:100))
p +
scale_x_continuous(trans = trans_reverser('log10')) +
annotation_logticks(sides = 'tb') +
theme_bw()
Edit: starting from v1.2.0 of the scales package, this will also work
library(scales)
p +
scale_x_continuous(
trans = compose_trans("log10", "reverse"),
breaks = c(100, 10, 1)
) +
annotation_logticks(sides = 'tb') +
theme_bw()
p +
scale_x_continuous(
trans = compose_trans("log10", "reverse"),
labels = label_log()
) +
annotation_logticks(sides = 'tb') +
theme_bw()
Created on 2020-11-14 by the reprex package (v0.3.0)
You can apply the logarithm directly inside the ggplot function, in the aes() specification:
require(ggplot2)
df <- data.frame(x=1:10, y=runif(10))
p <- ggplot(data=df, aes(x = log10(x), y=y)) + geom_point()
and then reverse the x axis
p + scale_x_reverse()
in this way your data is not altered, but you can scale the graph
Just thought I put updated answer to this question that does not require writing your own transformation. As of scales version 1.2.0 (released in April 2022), transformation composition is handled by the scales package directly. Use scale_x_continuous(), with the trans argument as a vector with both log10 and reverse. You need to put log10 before reverse or you'll get an error; the transformations are applied in the order specified.
p + scale_x_continuous(trans = c("log10", "reverse"))
The documentation for scales::compose_trans even has this usage as an example.

Resources