0
votes

I am trying to place images to a plot that needs to have fixed coordinates (x, y values are GPS coordinates and I want the map to scale correctly). If the ranges of x and y don't match the images are flatted.

I don't know if this is a bug or desired behavior. Is there a way how to make the image with original aspect ratio? The only thing that I came up with is to put invisible points to the corners to make the plot square again.

Simple example is as following:

require(tidyverse)
require(ggimage)

plot_image <- function(x_size, y_size) {

  dta_points <- crossing(x = c(-x_size, x_size), y = c(-y_size, y_size))
  dta_img <- data_frame(x = 0, y = 0, image = 'https://www.r-project.org/logo/Rlogo.png')

  ggplot(NULL, aes(x, y)) + 
    geom_point(data = dta_points) +
    geom_image(data = dta_img, aes(image = image), size = 1) +
    ggtitle(paste0('x_size: ', x_size, ', y_size: ', y_size)) +
    coord_fixed()
}

plot_image(x_size = 1, y_size = 1)
plot_image(x_size = 0.1, y_size = 1)
plot_image(x_size = 1, y_size = 0.1)

enter image description here

2

2 Answers

1
votes

try geom_custom,

library(ggplot2)
library(png)
library(grid)
library(egg)

i <- readPNG(system.file("img", "Rlogo.png", package="png"))
img <- data.frame(x = 6, y = 3)
img$g <-  list(rasterGrob(i, width=unit(24,"pt")))

ggplot(iris, aes(x = Sepal.Length, y = Petal.Length)) + 
  geom_point() +
  geom_custom(data=img, aes(x,y,data=g), grob_fun=identity) +
  coord_fixed()
1
votes

You can tweak xmin/xmax/ymin/ymax arguments inside annotation_custom to place the image at any place while deciding its aspect ratio:

library(ggplot2)
library(png)
library(grid)

download.file("https://www.r-project.org/logo/Rlogo.png", 'Rlogo.png', mode = 'wb')
image <- readPNG("Rlogo.png")
logo <- rasterGrob(image, interpolate = TRUE)

ggplot() + 
  annotation_custom(logo, xmin = -Inf, xmax = Inf, ymin = -Inf, ymax = Inf) 

Example:

ggplot(iris, aes(x = Sepal.Length, y = Petal.Length)) + 
  annotation_custom(logo, xmin = 7, xmax = 8, ymin = 2, ymax = 4) +
  geom_point()

Following up your comment:

You just need to specify the x & y aesthetics to preserve the original aspect ratio and size will help with scaling if needed:

library(ggimage)

dta_img <- data.frame(x = 6, y = 3, image = 'https://www.r-project.org/logo/Rlogo.png')

ggplot(iris, aes(x = Sepal.Length, y = Petal.Length)) + 
  geom_image(data = dta_img, aes(x, y, image = image), size = 0.1) +
  geom_point()

enter image description here

Please also check out leaflet, which has built-in features to create beautiful maps similar to the one you linked: Leaflet for R