UPDATE: changed data source so that the entire example can be run by anone on their own machine. Also, per Joachim's suggestion, I put a box around the blown up area of the map. Thoughts?
Here's a quick demo of creating a map with an inset within it using ggplot. The inset is achieved using the gridExtra package.
Install libraries
1 library(ggplot2)
2 library(maps)
3 library(maptools)
4 library(gridExtra)
5 library(rgeos)
Create a data frame
1 dat <- data.frame(ecosystem = rep(c("oak", "steppe", "prairie"), each = 8),
2 lat = rnorm(24, mean = 51, sd = 1), lon = rnorm(24, mean = -113, sd = 5))
3 head(dat)
ecosystem lat lon
1 oak 51.81 -109.1
2 oak 50.41 -115.0
3 oak 52.20 -112.5
4 oak 51.67 -114.8
5 oak 49.75 -105.4
6 oak 51.42 -114.6
Get maps using the maps library
1 # Get a map of Canada
2 canadamap <- data.frame(map("world", "Canada", plot = FALSE)[c("x", "y")])
3
4 # Get a map of smaller extent
5 canadamapsmall <- canadamap[canadamap$x < -90 & canadamap$y < 54, ]
6
7 # Make inset rectangle to show area of zoom
8 canadamapsmall_ <- na.omit(canadamapsmall) # omit NA's
9
10 # This should get your corner points for the box, picking min and max of
11 # lat and lon
12 insetrect <- data.frame(xmin = min(canadamapsmall_$x), xmax = max(canadamapsmall_$x),
13 ymin = min(canadamapsmall_$y), ymax = max(canadamapsmall_$y))
14 insetrect
xmin xmax ymin ymax
1 -133.1 -90.39 48.05 54
Make the maps
1 # The inset map, all of Canada
2 a <- ggplot(canadamap) +
3 theme_bw(base_size = 22) +
4 geom_path(data = canadamap, aes(x, y), colour = "black", fill = "white") +
5 geom_rect(data = insetrect, aes(xmin = xmin, xmax = xmax, ymin = ymin, ymax = ymax), alpha=0, colour="blue", size = 1, linetype=1) +
6 opts(panel.border = theme_rect(colour = 'black', size = 1, linetype=1),
7 panel.grid.major = theme_blank(), panel.grid.minor=theme_blank(),
8 panel.background = theme_rect( fill = 'white'),
9 legend.position = c(0.15,0.80), legend.key = theme_blank(),
10 axis.ticks = theme_blank(), axis.text.x=theme_blank(),
11 axis.text.y=theme_blank()) +
12 labs(x = '', y = '')
13
14 # The larger map, zoomed in, with the data
15 b <- ggplot(dat, aes(lon, lat, colour=ecosystem)) +
16 theme_bw(base_size = 22) +
17 geom_jitter(size=4, alpha=0.6) +
18 geom_path(data = canadamapsmall, aes(x, y), colour = "black", fill = "white") +
19 scale_size(guide="none") +
20 opts(panel.border = theme_rect(colour = 'black', size = 1, linetype=1),
21 panel.grid.major = theme_blank(), panel.grid.minor=theme_blank(),
22 panel.background = theme_rect( fill = 'white'),
23 legend.position = c(0.1,0.20), legend.text=theme_text(size=12, face='bold'),
24 legend.title=theme_text(size=12, face='bold'), legend.key = theme_blank(),
25 axis.ticks = theme_segment(size = 2)) +
26 labs(x = '', y = '')
Print the two maps together, one an inset of the other
This approach uses the gridExtra package for flexible alignment, etc. of ggplot graphs
1 grid.newpage()
2 vpb_ <- viewport(width = 1, height = 1, x = 0.5, y = 0.5) # the larger map
3 vpa_ <- viewport(width = 0.4, height = 0.4, x = 0.8, y = 0.8) # the inset in upper right
4 print(b, vp = vpb_)
5 print(a, vp = vpa_)

Get the .Rmd file used to create this post at my github account.
Written in Markdown, with help from knitr, and nice knitr highlighting/etc. in in RStudio.