Distorted image when adding text outside ggplot facets with gridExtra - r

I am trying to add the file name outside a plot area obtained with ggplot, using facet_wrap. I was pretty sure I found the solution in this post:
Add filename or other annotation to ggplot figures. However, applying the solution to my problem gives a distorted image.
The code to generate this is here:
require("gridExtra")
library(tidyverse)
df <- data.frame(x =runif(100, 1, 10),
y = runif(100, 1, 10),
myfacet = c("one", "two"))
p <- ggplot(data = df,
aes(x = x,
y = y)) +
geom_point() +
facet_wrap(~myfacet)
print(p)
script.name <- "myscript.R"
sub.label = textGrob(script.name,
gp=gpar(fontsize=6),
x = unit(1, "npc"),
hjust = 1,
vjust = 1)
ggsave(filename="../plots/myplot.png",
plot = arrangeGrob(p,
sub = sub.label,
clip = FALSE))
If I just use
ggsave(filename="../plots/myplot2.png",
plot = p)
I get the following image:
Please note that I need a solution that works outside the facets.
Could anyone provide a hint as to what is going on? Thank you!

grid.arrange(p, bottom = sub.label)

Related

How can I format the axes in plotRGB from the R raster package?

I'm trying to plot two plots side by side. One is a RasterStack for which I'm using plotRGB(). The axes are a mess however - it is plotting too many decimal places for the latitude and longitude. I'd also like to change the font size and text orientation.
This is straightforward in plot(), but I can't figure it out for plotRGB.
Can anyone help?
This is the code:
par(mar=c(4,5,4,2), mfrow = c(1, 2))
plotRGB(tayRGB, axes = TRUE, stretch = "lin", main = "RGB")
plot(knr, main = "Kmeans", cex.axis=0.96, col = viridis_pal(option="D")(10))
Can I recommend to use the function RStoolbox)::ggRGB instead of plotRGB. This will give you the full functionality of ggplot to customise your plot. A reproducible example:
set.seed(123)
R = raster(matrix(runif(400),20,20))
G = raster(matrix(runif(400),20,20))
B = raster(matrix(runif(400),20,20))
tayRGB = brick(list(R,G,B))
library(RStoolbox)
p1 = ggRGB(tayRGB, r=1, g=2, b=3, stretch = 'lin') +
scale_y_continuous(labels = scales::number_format(accuracy = 0.001)) +
scale_x_continuous(labels = scales::number_format(accuracy = 0.1)) +
theme(axis.title.x = element_text(size = 30),
axis.text.y = element_text(angle = 45))
p1
To plot your other plot side by side with this, you can either remake it as a ggplot. Or you can use ggplotify::base2grob to convert a base R plot into a grob.
p2 = ggplotify::base2grob(~plot(rnorm(100)))
cowplot::plot_grid(p1,p2)

R; plotting scatter plot and heat map side by side

I am trying to create an image showing a scatter plot and a heat map side by side. I create the scatter plot with geom_point and the heatmap with heatmap.2. I then use grid.draw to put them in the same image HOWEVER I cannot get the images to be the same size. How can I make sure they are the same height (this is important as they are ordered the same way and match each other)?
The code I have is:
grab_grob <- function(){
grid.echo()
grid.grab()
}
g1 <- ggplot(x, aes(x=VIPscore, y=reorder(metabolite, VIPscore))) + geom_point(colour="blue") + labs(y="", x="VIP score")
heatmap.2(xhm, cexRow=0.5, cexCol=1, Colv=FALSE, Rowv = FALSE, keep.dendro = FALSE, trace="none", key=FALSE, lwid = c(0.5, 0.5), col=heat.colors(ncol(xhm)))
g2 <- grab_grob()
grid.newpage()
lay <- grid.layout(nrow = 1, ncol=2)
pushViewport(viewport(layout = lay))
print(g1,vp=viewport(layout.pos.row = 1, layout.pos.col = 1))
grid.draw(editGrob(g2, vp=viewport(layout.pos.row = 1, layout.pos.col = 2, clip=TRUE)))
upViewport(1)
I have also tried the geom_tile (instead of heatmap.2) followed by grid.arrange; although the images now match in size colors are awful - they look flat across my data set.
A package called plotly might be of help here. Check out their API docs
library(plotly)
df <- data.frame(x = 1:1000,
y = rnorm(1000))
p1 <- plot_ly(df, x = x, y = y, mode = "markers")
p2 <- plot_ly(z = volcano, type = "heatmap")%>% layout(title = "Scatterplot and Heatmap Subplot")
subplot(p1, p2)
A drop-in solution could be to use the package "ComplexHeatmap".
https://bioconductor.org/packages/release/bioc/vignettes/ComplexHeatmap/inst/doc/s4.heatmap_annotation.html

How to superimpose bar plots in R?

I'm trying to create a figure similar to the one below (taken from Ro, Russell, & Lavie, 2001). In their graph, they are plotting bars for the errors (i.e., accuracy) within the reaction time bars. Basically, what I am looking for is a way to plot bars within bars.
I know there are several challenges with creating a graph like this. First, Hadley points out that it is not possible to create a graph with two scales in ggplot2 because those graphs are fundamentally flawed (see Plot with 2 y axes, one y axis on the left, and another y axis on the right)
Nonetheless, the graph with superimposed bars seems to solve this dual sclaing problem, and I'm trying to figure out a way to create it in R. Any help would be appreciated.
It's fairly easy in base R, by using par(new = T) to add to an existing graph
set.seed(54321) # for reproducibility
data.1 <- sample(1000:2000, 10)
data.2 <- sample(seq(0, 5, 0.1), 10)
# Use xpd = F to avoid plotting the bars below the axis
barplot(data.1, las = 1, col = "black", ylim = c(500, 3000), xpd = F)
par(new = T)
# Plot the new data with a different ylim, but don't plot the axis
barplot(data.2, las = 1, col = "white", ylim = c(0, 30), yaxt = "n")
# Add the axis on the right
axis(4, las = 1)
It is pretty easy to make the bars in ggplot. Here is some example code. No two y-axes though (although look here for a way to do that too).
library(ggplot2)
data.1 <- sample(1000:2000, 10)
data.2 <- sample(500:1000, 10)
library(ggplot2)
ggplot(mapping = aes(x, y)) +
geom_bar(data = data.frame(x = 1:10, y = data.1), width = 0.8, stat = 'identity') +
geom_bar(data = data.frame(x = 1:10, y = data.2), width = 0.4, stat = 'identity', fill = 'white') +
theme_classic() + scale_y_continuous(expand = c(0, 0))

zoom in a CDF figure

I have the below figure shows cdf. I am wondering how can I zoom in to show better the difference between four lines in the left upper part of the figure.
You can use coord_cartesian to zoom in. I don't know what you mean by having the zoom part and the whole in the same figure. If you want to have them side by side, you can use the multiplot function found in the Cookbook for R page. For example:
df <- data.frame(x = c(rnorm(100, 0, 3), rnorm(100, 0, 10)),
g = gl(2, 100))
p <- ggplot(df, aes(x, colour = g)) + stat_ecdf()
p1 <- p
p2 <- p + coord_cartesian(ylim = c(.75, 1))
multiplot(p1, p2)
Edit
Based on #Paul Lemmens' comment, you can use grid's viewport function in the following way:
pdf("~/Desktop/foo.pdf", width = 6, height = 6)
subvp <- viewport(width = .4, height = .4, x = .75, y = .25)
p1
print(p2, vp = subvp)
dev.off()
which gives the following output - adjust the details for your specific example:

Add filename or other annotation to ggplot figures

I use ggplot to make most of my graphics. These can be single panels, or faceted. To make it easier to track revisions, I would like to generate a small label in the corner of the plot that includes some text.
In pseudo code, I am looking for something like this:
# generate the initial plot
p <- ggplot()
# add the label
p + someAnnotationFunction(label = "Version 1.0", x = 1, y = 0,
hjust = "right", vjust = "bottom" )
# print
print(p)
Or: plot my label nestled in the lower right corner of my figure without messing up the existing ggplot graphics.
So far I'm not having any luck finding a solution. This (very interesting) method doesn't work if you have a full m x n table of facets. Methods using gridExtra tend to mess with the plots too much. So, does anyone have a way to add arbitrary text anywhere on a plot that was generated using ggplot?
Here's a worked solution using gridExtra(), based on Baptiste's comment:
require("ggplot2")
require("gridExtra")
# set our working directory
working.dir <- '/Users/aclifton/Documents/projects/Rcode'
setwd(working.dir)
# create a data frame
df <- data.frame(x =runif(100, 1, 10),
y = runif(100, 1, 10))
#create a plot
p <- ggplot(data = df,
aes(x = x,
y = y)) +
geom_point()
print(p)
We now have our plot, and the trick is adding that label and saving the overall plot using ggsave():
# label to show
sub.label = textGrob("Some kind of label",
gp=gpar(fontsize=6),
x = unit(1, "npc"),
hjust = 1,
vjust = 0)
ggsave(filename=file.path(working.dir,'DemoPlot.png'),
plot = arrangeGrob(p,
sub = sub.label,
clip = FALSE),
scale = 1,
width = 6.5,
height = 3.5,
units = c("in"),
dpi = 300)
Which gives you this:
By making a data frame of your annotations, you can add them on top of your plot using geom_text.
note <- data.frame(xVarName = c(1, 5), yVarName = c(1, 10),
text = c("Version 1.0", "April 26, 2014")
p + geom_text(data = anno, aes(label = text))
"Version 1.0" will show up in the bottom left and "April 26, 2014" will show up in the top right.
By making your notes in a separate dataframe, you can add multiple notes to one graph if desired.

Resources