Way to overlay an image on each ggplot object in a list using grid.raster?
Here is a possibile solution:
library(ggplot2)
library(purrr)
library(cowplot)
library(gridExtra)
library(magick)
stock_image <- image_read_svg('http://jeroen.github.io/images/tiger.svg', width = 400)
# Make 4 ggplot objects for example
any_ggplot1 <- qplot(mtcars$hp, mtcars$mpg)
any_ggplot2 <- qplot(mtcars$drat, mtcars$mpg)
any_ggplot3 <- qplot(mtcars$wt, mtcars$cyl)
any_ggplot4 <- qplot(mtcars$disp, mtcars$cyl)
# Make a list of them
plot_list <- list(any_ggplot1, any_ggplot2, any_ggplot3, any_ggplot4)
new_plot_list <- purrr::map(plot_list, function(x) {
ggdraw() +
draw_image(stock_image, x = 0.25, y = 0.25, scale=0.25) +
draw_plot(x)
})
grid.arrange(grobs=new_plot_list)
Inserting an image to ggplot2
try ?annotation_custom
in ggplot2
example,
library(png)
library(grid)
img <- readPNG(system.file("img", "Rlogo.png", package="png"))
g <- rasterGrob(img, interpolate=TRUE)
qplot(1:10, 1:10, geom="blank") +
annotation_custom(g, xmin=-Inf, xmax=Inf, ymin=-Inf, ymax=Inf) +
geom_point()
How to add a black overlay semi transparent layer above the background image in r?
Based on this answer I tried annotate()
instead of geom_rect()
, which does the trick:
ts_all_long %>%
filter(Country.Region == "Brazil") %>%
ggplot(aes(x = date, y = Confirmed_daily)) +
background_image(readJPEG("/home/johannes/Downloads/coronavirus-4972480_1920.jpg")) +
annotate("rect", xmin = min(ts_all_long$date), xmax = max(ts_all_long$date), ymin = -Inf, ymax = Inf,
fill = "black", alpha = 0.3) +
geom_area(size = 1, col = "#f08080", fill = "#f08080", alpha = 0.5)
Created on 2021-04-20 by the reprex package (v2.0.0)
However, I think it would actually look better to do something like this:
ts_all_long %>%
filter(Country.Region == "Brazil") %>%
ggplot(aes(x = date, y = Confirmed_daily)) +
background_image(readJPEG("/home/johannes/Downloads/coronavirus-4972480_1920.jpg")) +
geom_area(size = 1, col = "white", fill = "#f08080", alpha = 0.5)
Created on 2021-04-20 by the reprex package (v2.0.0)
how to fit the plot over a background image in R and ggplot2
You can set width and height arguments in rasterGrob
both equal to 1 "npc", which will force the image to fill the plot area. Then specify the height and width of the image when you save it to get the aspect ratio you desire. Theme and scale_y_reverse options can be used to control the appearance of the axes as demonstrated also below. note that we can also use the expand
parameter to ensure that the axes do not extend further than the image or data.
g <- rasterGrob(img, width=unit(1,"npc"), height=unit(1,"npc"), interpolate = FALSE)
g_ct <- ggplot(data=df_ct) +
annotation_custom(g, -Inf, Inf, -Inf, Inf) +
geom_path(aes_string(x=df_ct$X1, y=df_ct$X0), color='red', size=1) +
scale_y_reverse("",
labels = c(min(df_ct$X0), rep("", length(seq(min(df_ct$X0), max(df_ct$X0), 5))-2),max(df_ct$X0)),
breaks = seq(min(df_ct$X0), max(df_ct$X0), 5),
expand = c(0,0)) +
theme(plot.margin = unit(c(5,5,5,5), "mm"),
axis.line.x = element_blank(),
axis.ticks.x = element_blank(),
axis.text.x = element_blank(),
axis.line.y = element_blank(),
axis.ticks.y = element_line(size = 1),
axis.ticks.length = unit(5,'mm')) +
scale_x_continuous("")
g_ct
ggsave('test.png', height=5, width = 2, units = 'in')
Some data:
df_ct <- data.frame(X0 = 0:100)
df_ct$X1 = sin(df_ct$X0) +rnorm(101)
and a background image:
https://i.stack.imgur.com/aEG7I.jpg
Use ggplot to plot over an image with legend
The real "magic" for this is just fullpage=FALSE
in the call to ggimage()
, but you'll have to clean up axes a bit then:
ggimage(r, fullpage = FALSE, scale_axes = TRUE) +
geom_point(aes(x = x, y = y, colour = SEX),
data = toy, size = I(1), fill = NA) +
labs(x=NULL, y=NULL) +
theme(axis.text=element_blank()) +
theme(axis.ticks=element_blank())
You should prbly clean up the legend, too and I'd suggest lightening the base image a bit since it will be difficult to see the contrast between it and the colors you're going to overlay (unless they're large objects).
heat map with image as background
Something like this?
library(ggplot2)
data(hadley, package="ggmap")
img <- hadley
set.seed(1) # for reproducible example
df <- data.frame(x=rnorm(100,mean=c(150,250),sd=25),
y=rnorm(100,mean=480, sd=20))
ggplot(df, aes(x,y)) +
annotation_raster(img, xmin=-Inf, xmax=Inf, ymin=-Inf, ymax=Inf)+
stat_density2d(geom = "polygon", aes(fill=..level..)) +
geom_point(size=0.5)+
scale_fill_gradient(low="green",high="red") +
scale_x_continuous(limits=c(0,dim(img)[2]),expand=c(0,0))+
scale_y_continuous(limits=c(0,dim(img)[1]),expand=c(0,0))+
coord_fixed()
The main idea is to use geom="polygon"
with aes(fill=..level..)
. The image itself can be added using annotation_raster(...)
as described in this post.
With sincere apologies to Hadley Wickham.
Related Topics
How to Reverse Legend (Labels and Color) So High Value Starts at Bottom
Create a Dataframe with Random Numbers in Each Column
How to Transpose a Tibble() in R
As(X, 'Double') and As.Double(X) Are Inconsistent
Draw a Trend Line Using Ggplot
How to Apply Geom_Smooth() for Every Group
R: Replacing Nas in a Data.Frame with Values in the Same Position in Another Dataframe
Produce a Table Spanning Multiple Pages Using Kable()
Replace Nas with Mean of the Same Column of a Data.Table
Generate Random Integers Between Two Values with a Given Probability Using R
R 3.5 Is Not Available for Linux
Reduce Space Between Grid.Arrange Plots
Send a Text String Containing Double Quotes to Function
Scales = "Free" Works for Facet_Wrap But Doesn't for Facet_Grid