I am trying to add my company logo under all of our charts. I managed to do so however the end result looks a bit disappointing. The logo looks all blurry despite me using high res image.
Is there any way I can improve this?
(Note that the R logo I use has the same resolution as my company logo's res. They are all 1000*1000px)
Below is my code:
library(ggplot2)
library(png)
library(gridExtra)
library(grid)
dev.off(dev.list()["RStudioGD"])
gg <- ggplot(mtcars, aes(x = mpg, y = wt)) +
theme_minimal() +
geom_count() +
labs(title = "Title Goes Here", x = "", y = "")
img <- readPNG("R-logo.png")
gg = gg +
annotation_custom(rasterGrob(img),
xmin=0.95*min(mtcars$mpg)-1, xmax=0.95*min(mtcars$mpg)+1,
ymin=0.6*min(mtcars$wt)-0.7, ymax=0.6*min(mtcars$wt)+0.5) +
theme(plot.margin=margin(5,10,40,5))
# Turn off clipping
gt <- ggplot_gtable(ggplot_build(gg))
gt$layout$clip[gt$layout$name=="panel"] <- "off"
png('chart.png', width = 600, height = 500, units = "px",type='cairo',res=72)
grid.draw(gt)
dev.off()
Actually, I found the way to properly scale the logo before laying over the plot. The magick package works wonderfully.
library(magick)
img <- image_read("R-logo.png")
img <- image_scale(img, "50")
Related
Problem
I would like to insert an image in between some text in the caption of my ggplot.
What I found on sofar is this solution using some gtable hacking.
But this solution is somewhat unviable for me, because I want to add text before and after the image. Besides, it doesn't resize the image to the actual fontsize of the caption.
library(tidyverse)
library(magick)
library(grid)
library(gtable)
ggplot(iris,
aes(x = Sepal.Length, y = Sepal.Width)) +
geom_point() +
theme(plot.caption = element_text(hjust=0,
size = 10)) +
labs(caption = "\uA9 *INSERT MY COMPANY LOGO HERE* My fabulous company, 2019")
my_logo <- image_read("https://upload.wikimedia.org/wikipedia/commons/3/3e/Phalaenopsis_JPEG.png")
print(my_logo)
Goal
What I want to achieve is this. Note that the logo's (my_logo) vertical size is equal to the fontsize of the caption.
The answer you link to provides all the ingredients,
library(ggplot2)
library(grid)
library(dplyr)
library(gtable)
lg <- textGrob(label = "\uA9", x = unit(0, "npc"), just = "left")
rg <- textGrob(label = "My fabulous company, 2019", x = unit(0, "npc"), just = "left")
mg <- png::readPNG(system.file("img", "Rlogo.png", package="png")) %>%
rasterGrob(interpolate = TRUE, height = grobHeight(rg))
p <- ggplot(mtcars, aes(wt, mpg)) +
geom_point() +
labs(caption="") # to create space for title
# convert to grob
gt <- ggplotGrob(p)
# create new title as a tableGrob with separate cells for image & text
new.title <- gtable_row('caption', grobs = list(lg,mg,rg),
widths = unit.c(grobWidth(lg), grobWidth(mg), unit(1,"null")),
height=unit(1,"null")) %>%
# optional: adda fixed amt of space between image & text
gtable_add_col_space(width = unit(5, "pt"))
# assign new title back to gt
gt$grobs[[which(gt$layout$name == "caption")]] <- new.title
grid.newpage()
grid.draw(gt)
How to add image logo outside the plotting areas for ggplot2. Tried rasterGrob function from 'grid' package, but that keep's the image inside plot area.
Here is the starter script:
library(ggplot2)
library(png)
library(gridExtra)
library(grid)
gg <- ggplot(df1, aes(x = mpg, y = wt)) +
theme_minimal() +
geom_count() +
labs(title = "Title Goes Here", x = "", y = "")
img <- readPNG("fig/logo.png")
Here is the outcome I am looking for.
I can add the annotation on the right side, but the logo on the left is where I am getting challenged.
You can add the elements with annotation_custom but you need to turn off clipping for the images to show up when they're outside the plot area. I've changed your example slightly in order to make it reproducible.
library(ggplot2)
library(png)
library(gridExtra)
library(grid)
gg <- ggplot(mtcars, aes(x = mpg, y = wt)) +
theme_minimal() +
geom_count() +
labs(title = "Title Goes Here", x = "", y = "")
img = readPNG(system.file("img", "Rlogo.png", package="png"))
gg = gg +
annotation_custom(rasterGrob(img),
xmin=0.95*min(mtcars$mpg)-1, xmax=0.95*min(mtcars$mpg)+1,
ymin=0.62*min(mtcars$wt)-0.5, ymax=0.62*min(mtcars$wt)+0.5) +
annotation_custom(textGrob("Footer goes here", gp=gpar(col="blue")),
xmin=max(mtcars$mpg), xmax=max(mtcars$mpg),
ymin=0.6*min(mtcars$wt), ymax=0.6*min(mtcars$wt)) +
theme(plot.margin=margin(5,5,30,5))
# Turn off clipping
gt <- ggplot_gtable(ggplot_build(gg))
gt$layout$clip[gt$layout$name=="panel"] <- "off"
grid.draw(gt)
Another option is to use ggplot's caption feature to add the text footer, which saves some code:
gg = gg +
annotation_custom(rasterGrob(img),
xmin=0.95*min(mtcars$mpg)-1, xmax=0.95*min(mtcars$mpg)+1,
ymin=0.62*min(mtcars$wt)-0.5, ymax=0.62*min(mtcars$wt)+0.5) +
labs(caption="Footer goes here") +
theme(plot.margin=margin(5,5,15,5),
plot.caption=element_text(colour="blue", hjust=1.05, size=15))
# Turn off clipping
gt <- ggplot_gtable(ggplot_build(gg))
gt$layout$clip[gt$layout$name=="panel"] <- "off"
grid.draw(gt)
Jut adding an updated method from the terrific package Magick:
library(ggplot2)
library(magick)
library(here) # For making the script run without a wd
library(magrittr) # For piping the logo
# Make a simple plot and save it
ggplot(mpg, aes(displ, hwy, colour = class)) +
geom_point() +
ggtitle("Cars") +
ggsave(filename = paste0(here("/"), last_plot()$labels$title, ".png"),
width = 5, height = 4, dpi = 300)
# Call back the plot
plot <- image_read(paste0(here("/"), "Cars.png"))
# And bring in a logo
logo_raw <- image_read("http://hexb.in/hexagons/ggplot2.png")
# Scale down the logo and give it a border and annotation
# This is the cool part because you can do a lot to the image/logo before adding it
logo <- logo_raw %>%
image_scale("100") %>%
image_background("grey", flatten = TRUE) %>%
image_border("grey", "600x10") %>%
image_annotate("Powered By R", color = "white", size = 30,
location = "+10+50", gravity = "northeast")
# Stack them on top of each other
final_plot <- image_append(image_scale(c(plot, logo), "500"), stack = TRUE)
# And overwrite the plot without a logo
image_write(final_plot, paste0(here("/"), last_plot()$labels$title, ".png"))
Below is a plot that I want to include in a paper. The problem is the width of my plot which is to small (that make x-axix not readable at all)
Here is the ggplot2 code myCode.r :
require("ggplot2")
all <- read.csv(file="benchmark/bench.query.csv", head=TRUE, sep=";")
w <- subset(all, query %in% c("sort.q1", "sort.q2", "sort.q3", "sort.q4", "sort.q5"))
w$rtime <- as.numeric(sub(",", ".", w$rtime, fixed=TRUE))
p <- ggplot(data=w, aes(x=query, y=rtime, colour=triplestore, shape=triplestore))
p <- p + scale_shape_manual(values = 0:length(unique(w$triplestore)))
p <- p + geom_point(size=4)
p <- p + geom_line(size=1,aes(group=triplestore))
p <- p + labs(x = "Requêtes", y = "Temps d'exécution (log10(ms))")
p <- p + scale_fill_continuous(guide = guide_legend(title = NULL))
p <- p + facet_grid(trace~type)
p <- p + theme_bw()
ggsave(file="bench_query_sort.pdf")
print (p)
I've look around to see how to enlarge the plot, but I found nothing.
Any idea about what to add/delete/modify in my code ?
Inside a Jupyter notebook I found the following helpful:
# Make plots wider
options(repr.plot.width=15, repr.plot.height=8)
Probably the easiest way to do this, is by using the graphics devices (png, jpeg, bmp, tiff). You can set the exact width and height of an image as follows:
png(filename="bench_query_sort.png", width=600, height=600)
ggplot(data=w, aes(x=query, y=rtime, colour=triplestore, shape=triplestore)) +
scale_shape_manual(values = 0:length(unique(w$triplestore))) +
geom_point(size=4) +
geom_line(size=1,aes(group=triplestore)) +
labs(x = "Requêtes", y = "Temps d'exécution (log10(ms))") +
scale_fill_continuous(guide = guide_legend(title = NULL)) +
facet_grid(trace~type) +
theme_bw()
dev.off()
The width and height are in pixels. This is especailly useful when preparing images for publishing on the internet. For more info, see the help-page with ?png.
Alternatively, you can also use ggsave to get the exact dimensions you want. You can set the dimensions with:
ggsave(file="bench_query_sort.pdf", width=4, height=4, dpi=300)
The width and height are in inches, with dpi you can set the quality of the image.
If you are using RMD(R Markdown) this would be the easiest way to define width and height.
```{r fig.align="center", echo = FALSE,fig.width = 14}
<write the code for your plot here>
```
Note: options() not worked for me so I used this method
It seems there is some padding around the title, which I can't figure out how to change, any thoughts?
xy <- data.frame(x=1:10, y=10:1)
plot <- ggplot(data = xy)+ geom_point(aes(x = x, y = y))
plot <- plot + opts(plot.background = theme_rect(colour = 'purple', fill = 'pink', size = 3, linetype='dashed'))
plot
plot + opts(title = 'Graph Title')
plot
If you run this, hold a piece of paper on your screen (old school, I know) in line with the top of the G and T from the title, then run the plot again, you'll see you have some grey above your paper. Which I can only presume is indicative of some padding around the title? Or likewise, if you run it without the title and hold the paper (above) in line with the end of the pink background, then run it with the title, the top of the G and T are below the paper.
Example is essentially from https://github.com/hadley/ggplot2/wiki/Graph-Panel-Attributes
This suggests there is a line height option but it appears to do nothing http://www.inside-r.org/packages/cran/ggplot2/docs/theme_text
So here is a hack:
p <- plot + opts(title = 'Graph Title')
p <- ggplot_gtable(ggplot_build(p))
p$heights[[2]] <- p$heights[[2]]-unit(0.5, "lines")
grid.draw(p)
This code remove the padding.
But I'd recommend to send a feature request: https://github.com/hadley/ggplot2/issues?milestone=
Is it possible to insert a raster image or a pdf image underneath a geom_line() on a ggplot2 plot?
I wanted to be quickly able to plot data over a previously calculated plot that takes a long time to generate as it uses a large amount of data.
I read through this example. However, as it is over one year old I thought there might be a different way of doing this now.
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()
Could also use the cowplot R package (cowplot is a powerful extension of ggplot2). It will also need the magick package. Check this introduction to cowplot vignette.
Here is an example for both PNG and PDF background images.
library(ggplot2)
library(cowplot)
library(magick)
# Update 2020-04-15:
# As of version 1.0.0, cowplot does not change the default ggplot2 theme anymore.
# So, either we add theme_cowplot() when we build the graph
# (commented out in the example below),
# or we set theme_set(theme_cowplot()) at the beginning of our script:
theme_set(theme_cowplot())
my_plot <-
ggplot(data = iris,
mapping = aes(x = Sepal.Length,
fill = Species)) +
geom_density(alpha = 0.7) # +
# theme_cowplot()
# Example with PNG (for fun, the OP's avatar - I love the raccoon)
ggdraw() +
draw_image("https://i.stack.imgur.com/WDOo4.jpg?s=328&g=1") +
draw_plot(my_plot)
# Example with PDF
ggdraw() +
draw_image(file.path(R.home(), "doc", "html", "Rlogo.pdf")) +
draw_plot(my_plot)
Also, as #seabass20 asked in the comment below, we can also give a custom position and scale to the image. Below is an example inspired from help(draw_image). One needs to fine tune the parameters x, y, and scale until gets the desired output.
logo_file <- system.file("extdata", "logo.png", package = "cowplot")
my_plot_2 <- ggdraw() +
draw_image(logo_file, x = 0.3, y = 0.4, scale = .2) +
draw_plot(my_plot)
my_plot_2
Created on 2020-04-15 by the reprex package (v0.3.0)
Just adding an update from the terrific Magick package:
library(ggplot2)
library(magick)
library(here) # For making the script run without a wd
library(magrittr) # For piping the logo
# Make a simple plot and save it
ggplot(mpg, aes(displ, hwy, colour = class)) +
geom_point() +
ggtitle("Cars") +
ggsave(filename = paste0(here("/"), last_plot()$labels$title, ".png"),
width = 5, height = 4, dpi = 300)
# Call back the plot
plot <- image_read(paste0(here("/"), "Cars.png"))
# And bring in a logo
logo_raw <- image_read("http://hexb.in/hexagons/ggplot2.png")
# Scale down the logo and give it a border and annotation
# This is the cool part because you can do a lot to the image/logo before adding it
logo <- logo_raw %>%
image_scale("100") %>%
image_background("grey", flatten = TRUE) %>%
image_border("grey", "600x10") %>%
image_annotate("Powered By R", color = "white", size = 30,
location = "+10+50", gravity = "northeast")
# Stack them on top of each other
final_plot <- image_append(image_scale(c(plot, logo), "500"), stack = TRUE)
# And overwrite the plot without a logo
image_write(final_plot, paste0(here("/"), last_plot()$labels$title, ".png"))
Following up on #baptiste's answer, you don't need to load the grob package and convert the image if you use the more specific annotation function annotation_raster().
That quicker option could look like this:
# read picture
library(png)
img <- readPNG(system.file("img", "Rlogo.png", package = "png"))
# plot with picture as layer
library(ggplot2)
ggplot(mapping = aes(1:10, 1:10)) +
annotation_raster(img, xmin = -Inf, xmax = Inf, ymin = -Inf, ymax = Inf) +
geom_point()
Created on 2021-02-16 by the reprex package (v1.0.0)