Inserting an image to ggplot outside the chart area
When faceting, annotation_custom
draws the annotation in all panels. Therefore, annotation-custom
might not be the best way to go. Here are two attempts using functions from the grid
package. Neither is entirely automatic, but you might be able to adapt one or the other to meet your needs. They set up a 2 X 2 grid, shown using the grid.show.layout()
command. In the first, the faceted plot fills the entire panel, and the top right viewport contains the logo. It just so happens that in your plot, there is clear space for the logo. Note how layout.pos.row
and layout.pos.col
give the rows and columns occupied by a viewport within the layout.
library(ggplot2)
library(png)
library(grid)
# Get the logo
img <- readPNG(system.file("img", "Rlogo.png", package="png"))
g <- rasterGrob(img)
# Set the size of the viewport to contain the logo
size = unit(2, "cm")
# Get the graph
d <- ggplot(diamonds, aes(carat, price)) +
xlim(0, 2) +
stat_binhex(na.rm = TRUE) +
labs(title = 'Title') +
theme(aspect.ratio = 1) +
facet_wrap(~ color, scales = "free_x")
# Set up the layout for grid
heights = unit.c(size, unit(1, "npc") - size)
widths = unit.c(unit(1, "npc") - size, size)
lo = grid.layout(2, 2, widths = widths, heights = heights)
# Show the layout
grid.show.layout(lo)
# Position the elements within the viewports
grid.newpage()
pushViewport(viewport(layout = lo))
# The plot
pushViewport(viewport(layout.pos.row=1:2, layout.pos.col = 1:2))
print(d, newpage=FALSE)
popViewport()
# The logo
pushViewport(viewport(layout.pos.row=1, layout.pos.col = 2))
print(grid.draw(g), newpage=FALSE)
popViewport()
popViewport()
# To save the object
g = grid.grab()
grid.newpage()
grid.draw(g)
The title does not entirely align with the logo. One fix is to remove the title from the ggplot, draw a separate textGrob that contains the title, then position the textGrob in the top left viewport beside the viewport that contains the logo.
# Get the logo
img <- readPNG(system.file("img", "Rlogo.png", package="png"))
g <- rasterGrob(img)
# Set the size of the viewport to contain the logo
size = unit(2, "cm")
# Get the graph
d <- ggplot(diamonds, aes(carat, price)) +
xlim(0, 2) +
stat_binhex(na.rm = TRUE) +
# labs(title = 'Title') +
theme(aspect.ratio = 1) +
facet_wrap(~ color, scales = "free_x")
# and the title
title = textGrob("Title", gp = gpar(face = "bold", cex = 2))
# Set up the layout for grid
heights = unit.c(size, unit(1, "npc") - size)
widths = unit.c(unit(1, "npc") - 1.5*size, size)
lo = grid.layout(2, 2, widths = widths, heights = heights)
# Show the layout
grid.show.layout(lo)
# Position the elements within the viewports
grid.newpage()
pushViewport(viewport(layout = lo))
# The plot
pushViewport(viewport(layout.pos.row=2, layout.pos.col = 1:2))
print(d, newpage=FALSE)
popViewport()
# The logo
pushViewport(viewport(layout.pos.row=1, layout.pos.col = 2))
print(grid.draw(g), newpage=FALSE)
popViewport()
# The title
pushViewport(viewport(layout.pos.row=1, layout.pos.col = 1))
print(grid.draw(title), newpage=FALSE)
popViewport()
popViewport()
# To save the object
g = grid.grab()
grid.newpage()
grid.draw(g)
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 image to ggplot2 under the grid?
It's possible in the development version of ggplot2.
How to install it see this answer: https://stackoverflow.com/a/9656182/4265407
Minimal working example:
library(devtools)
dev_mode(on=T)
library(ggplot2)
library(png)
library(grid)
img <- readPNG(system.file("img", "Rlogo.png", package="png"), TRUE)
gpp <- rasterGrob(img, interpolate=TRUE)
gpp$width <- unit(1, "npc")
gpp$height <- unit(1, "npc")
df <- data.frame(x=seq(1,2,0.01),y=seq(1,2,0.01))
ggplot(df,aes(x=x,y=y)) +
annotation_custom(gpp, xmin=1, xmax=2.5, ymin=1, ymax=1.5) +
geom_point() + theme(panel.ontop=TRUE,
panel.background = element_rect(colour = NA,fill="transparent"))
How can I add a logo to a ggplot visualisation?
You could use the cowplot
package to easily add an image to any plot made with ggplot
. I used the R logo as the image that needs to be added to the plot (using magick
package to read it). One advantage of using cowplot
is that you can easily specify the size and position of both the plot and the image.
library(cowplot)
library(magick)
img <- image_read("Logo.png")
# Set the canvas where you are going to draw the plot and the image
ggdraw() +
# Draw the plot in the canvas setting the x and y positions, which go from 0,0
# (lower left corner) to 1,1 (upper right corner) and set the width and height of
# the plot. It's advisable that x + width = 1 and y + height = 1, to avoid clipping
# the plot
draw_plot(p,x = 0, y = 0.15, width = 1, height = 0.85) +
# Draw image in the canvas using the same concept as for the plot. Might need to
# play with the x, y, width and height values to obtain the desired result
draw_image(img,x = 0.85, y = 0.02, width = 0.15, height = 0.15)
Inserting an image to a bar chart in ggplot
One option is to use ggimage
. Source: https://guangchuangyu.github.io/pkgdocs/ggimage.html. Try this:
library(ggplot2)
library(ggimage)
library(dplyr)
set.seed(1234)
img <- list.files(system.file("extdata", package="ggimage"),
pattern="png", full.names=TRUE)
df = data.frame(
group = c('a', 'b', 'c'),
value = 1:3,
image = sample(img, size=3, replace = TRUE)
) %>%
mutate(value1 = .5 * value)
ggplot(df, aes(group, value)) +
geom_col() +
geom_image(aes(image=image, y = value1), size=.2)
Created on 2020-03-19 by the reprex package (v0.3.0)
Add horizontal lines outside plot area in ggplot2
You can set coord_cartesian(clip = "off")
and add a couple of annotation_custom
calls. This allows plotting relative to the panel without having to specify co-ordinates relative to your data:
ggplot(midwest, aes(x=area, y=poptotal)) +
geom_point(aes(col=state, size=popdensity)) +
geom_smooth(method="loess", se=F) +
xlim(c(0, 0.1)) +
ylim(c(0, 500000)) +
labs(y="Population",
x="Area",
title="FIGURE 4: Scatterplot",
caption = "Source: midwest") +
coord_cartesian(clip = "off") +
annotation_custom(grid::linesGrob(x = c(-0.12, 1.19), y = c(1.03, 1.03))) +
annotation_custom(grid::linesGrob(x = c(-0.12, 1.19), y = c(-.07, -.07))) +
theme(plot.background = element_rect(colour="black", size = 1),
plot.title = element_text(size = 16, face = 2, vjust = 5, hjust = -0.2),
plot.margin = margin(20, 20, 20, 20))
Add text outside plot area
I'm not entirely sure what you're trying to do so this may or may not generalise well.
That said, one possibility is to use annotate
with coord_cartesian(clip = "off")
to allow text outside the plot area.
ggplot(mtcars, aes(mpg, cyl, color = vs)) +
geom_line() +
annotate("text", x = 12.5, y = 3.5, label = "Arbitrary text") +
coord_cartesian(ylim = c(4, 8), clip = "off")
ggplot adding image on top-right in two plots with different scales
We can automate the process of specifying the location and scales, so that you don't need to change the locations manually, as shown in the following example:
get.xy <- function(p) {
g_data <- ggplot_build(p)
data.frame(xmax = max(g_data$data[[1]]$x),
ymax = max(g_data$data[[1]]$y),
xmin = min(g_data$data[[1]]$x),
ymin = min(g_data$data[[1]]$y))
}
# this returns the dataframe with required x, y params for annotation_custom,
# ensuring the size and position of the image constant
get.params.df <- function(p0, p1, width, height) {
df0 <- cbind.data.frame(get.xy(p0), width=width, height=height)
df1 <- cbind.data.frame(get.xy(p1))
df1$width <- df0$width*(df1$xmax-df1$xmin)/(df0$xmax-df0$xmin)
df1$height <- df0$height*(df1$ymax-df1$ymin)/(df0$ymax-df0$ymin)
df <- rbind(df0, df1)
return(data.frame(xmin=df$xmax-df$width, xmax=df$xmax+df$width, ymin=df$ymax-df$height, ymax=df$ymax+df$height))
}
p0 <- plt(am0)
p1 <- plt(am1)
df <- get.params.df(p0, p1, width=10, height=10)
# adding image
library(gridExtra)
grid.arrange(
p0 + annotation_custom(rasterGrob(img), xmin=df[1,1],xmax=df[1,2], ymin=df[1,3], ymax=df[1,4]),
p1 + annotation_custom(rasterGrob(img), xmin=df[2,1],xmax=df[2,2], ymin=df[2,3], ymax=df[2,4])
)
If you want bigger image change the width height parameter only, everything else remains unchanged.
df <- get.params.df(p0, p1, width=25, height=25)
library(gridExtra)
grid.arrange(
p0 + annotation_custom(rasterGrob(img), xmin=df[1,1],xmax=df[1,2], ymin=df[1,3], ymax=df[1,4]),
p1 + annotation_custom(rasterGrob(img), xmin=df[2,1],xmax=df[2,2], ymin=df[2,3], ymax=df[2,4])
)
Related Topics
Linear Model and Dplyr - a Better Solution
Apply a Function to Groups Within a Data.Frame in R
Detect Non Ascii Characters in a String
R Library for Discrete Markov Chain Simulation
How to Remove Empty Data Frames from a List
Caching the Mean of a Vector in R
Run a Bash Script from an R Script
Creating Legend with Circles Leaflet R
Using a Static (Prebuilt) PDF Vignette in R Package
Daily Time Series with Ts.. How to Specify Start and End
Glpk: No Such File or Directory Error When Trying to Install R Package
One-Class Classification with Svm in R
Calculate Mean Across Rows with Na Values in R
Can Ggplot Theme Formatting Be Saved as an Object
How to Remove Rows That Have Only 1 Combination for a Given Id
R How to Convert a Numeric into Factor with Predefined Labels