5

Problem

I want to draw a number of arrows on a map. With some googling, I've learned that annotation_custom with rasterGrob can do the thing:

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

img = readPNG('floorplan.png')
g = rasterGrob(img, interpolate = TRUE)

data = read.csv('est_err_structured.csv', header = FALSE)
x1 = data$V1
y1 = data$V2
x2 = data$V3
y2 = data$V4

p = ggplot() +
geom_segment(data = data, mapping = aes(x = x1, y = y1, xend = x2, yend = y2),
            arrow = arrow(length = unit(0.2, 'cm'))) +
annotation_custom(g, xmin = -Inf, xmax = Inf, ymin = -Inf, ymax = Inf) +
xlab('x (m)') +
ylab('y (m)') +
theme_bw()

pdf('err_on_map.pdf')
p
dev.off()

However, when I run this script, I only got arrows but not background image:

enter image description here

Attachment

References

Community
  • 1
  • 1
Jeon
  • 4,000
  • 4
  • 28
  • 73

1 Answers1

3

You need to study ggplot2 a bit more. E.g., the variables mapped within aes are taken from the data.frame defined as data and in this example you must pass it to ggplot. I think annotation_custom somehow needs it to get the proper coordinates or dimensions.

p = ggplot(data) +
  annotation_custom(g, xmin = -Inf, xmax = Inf, ymin = -Inf, ymax = Inf) +
  geom_segment(aes(x = V1, y = V2, xend = V3, yend = V4),
               arrow = arrow(length = unit(0.2, 'cm'))) +
  xlab('x (m)') +
  ylab('y (m)') +
  theme_bw()

You'll need to pass the plot width and height to pdf in order to align the image correctly with the plot.

resulting plot

Edit:

@baptiste recommends annotation_raster, which makes the positioning easier:

ggplot(data) +
  annotation_raster(img, xmin = 50, xmax = 600, ymin = 20, ymax = 400) +
  geom_segment(aes(x = V1, y = V2, xend = V3, yend = V4),
               arrow = arrow(length = unit(0.2, 'cm'))) +
  coord_cartesian(xlim = c(50, 600), ylim = c(20, 400)) +
  xlab('x (m)') +
  ylab('y (m)') +
  theme_bw()

resulting plot 2

Roland
  • 127,288
  • 10
  • 191
  • 288
  • one could argue that it's a bug, since any data.frame, e.g. `ggplot(iris)`, will do. – baptiste Aug 10 '16 at 07:47
  • @baptiste I vaguely remember you saying that `annotation_custom` is a horrible hack. :) – Roland Aug 10 '16 at 07:50
  • a buggy/unfinished function, yes. But quite useful nonetheless (what I consider a horrible hack is when it's combined with clip=off to place things outside the panel). Anyway, here annotation_raster might work too. – baptiste Aug 10 '16 at 07:53
  • @baptiste Yes, but it seems to have the same "bug". – Roland Aug 10 '16 at 08:01