Last active
November 3, 2020 16:34
-
-
Save zachcp/f2429fc17cf6c59d0967 to your computer and use it in GitHub Desktop.
ggrepel with maps
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
--- | |
title: "ggrepel to plot on busy maps" | |
author: "zachcp" | |
date: "March 1, 2016" | |
output: html_document | |
--- | |
```{r, warning=FALSE, message=FALSE} | |
library(rvest) | |
library(dplyr) | |
library(png) | |
library(sp) | |
library(maps) | |
library(rgeos) | |
library(grid) | |
library(ggplot2) | |
library(ggthemes) | |
``` | |
## Download Flags | |
Download a bunch of flag files from Wikipedia. | |
```{r} | |
#' Download Map files from Wikimedia | |
process_flagname <- function(fname,outdir="./flags/", prefix="http:"){ | |
flag <- strsplit(fname, ",")[[1]][[1]] | |
flag <- strsplit(flag, " ")[[1]][[1]] | |
flagimgname <- strsplit(flag, "/")[[1]][[9]] | |
countryname <- strsplit(flagimgname, "\\.")[[1]][[1]] | |
countryname <- strsplit(countryname, "_")[[1]][[3]] | |
flagurl <- paste0(prefix,flag) | |
newflag <- paste0(outdir, countryname,".png") | |
download.file(flagurl, destfile = newflag) | |
print(paste0("Downloading flag iamge for ", countryname, ".")) | |
} | |
flags <- read_html("https://en.wikipedia.org/wiki/Gallery_of_sovereign_state_flags") | |
flagimages <- flags %>% | |
html_nodes(".thumbborder") %>% | |
html_attr("srcset") | |
#get all the images | |
#lapply(flagimages, process_flagname) | |
# df of the downloaded flagfiles | |
flagfiles <- data.frame(flag = list.files("flags",pattern = "*.png")) | |
countries <- as.character( | |
lapply(as.character(flagfiles$flag), function(x){strsplit(x,"\\.")[[1]][[1]]})) | |
flagfiles$country <- countries | |
``` | |
## Function that calls ggrepel | |
```{r} | |
findboxes <- function(df, xcol, ycol, | |
pad_point_x, pad_point_y, | |
boxsize, | |
xlim, ylim, | |
force = 1e-6, maxiter = 20000) { | |
#x and y posiitons as a dataframe | |
posdf <- df[c(xcol,ycol)] | |
#returnd a df where columns are points | |
boxdf <- apply(posdf,1,function(row) { xval <- row[xcol] | |
yval <- row[ycol] | |
return(c(xval, | |
yval, | |
xval + boxsize, | |
yval + boxsize))}) | |
# columns are x1,y1,x2,y2 | |
boxmatrix = as.matrix(t(boxdf)) | |
moved <- ggrepel:::repel_boxes(data_points=as.matrix(posdf), | |
pad_point_x=pad_point_x, | |
pad_point_y=pad_point_y, | |
boxes = boxmatrix, | |
xlim=xlim, | |
ylim=ylim, | |
force=force, | |
maxiter=maxiter) | |
finaldf <- cbind(posdf, moved) | |
names(finaldf) <- c("x1","y1","x2","y2") | |
return(finaldf) | |
} | |
``` | |
## BaseMap | |
Process countries and get centroid starting positions. | |
```{r} | |
# get centroids of countries | |
world <- map_data("world") | |
getLabelPoint <- function(country) { | |
rgeos::gCentroid(SpatialPoints(country[c('long','lat')]))} | |
centroids <- by(world, world$region, getLabelPoint) | |
centnames <- names(centroids) | |
centroids <- as.data.frame(do.call(rbind, centroids) ) | |
row.names(centroids) <- centnames | |
names(centroids) <- c('long', 'lat') | |
gg <- ggplot(world) | |
gg <- gg + geom_map( | |
data=world, | |
map=world, | |
aes(x=long,y=lat, map_id=region), | |
fill="grey80") | |
gg <- gg + theme_map() | |
gg | |
``` | |
## Add Flags to Map | |
Don't use ggrepel, just place them on the map. | |
```{r} | |
centroids %>% | |
add_rownames("country") %>% | |
inner_join(flagfiles, by=c("country")) %>% | |
mutate(pngfile = paste0("./flags/",flag)) -> flagfiles | |
apply(flagfiles, | |
1, | |
function(x) | |
{img <- readPNG(x['pngfile']) | |
g <- rasterGrob(img, interpolate=TRUE) | |
lat <- as.numeric(x['lat']) | |
long <- as.numeric(x['long']) | |
return(list(grob=g, long=long,lat=lat)) | |
}) -> grobs | |
addmap <- function(gg,g){ | |
grob <- g$grob | |
lat <- g$lat | |
long <- g$long | |
#print(paste(lat,long)) | |
xdiff = 5 | |
ydiff = 5 | |
gg <- gg + annotation_custom(grob, | |
xmin = long - xdiff, | |
xmax = long + xdiff, | |
ymin = lat - ydiff, | |
ymax = lat + ydiff) | |
return(gg) | |
} | |
# create Map | |
Reduce(addmap,grobs,gg) | |
``` | |
## Use ggrepel with Force=0.2 to plot | |
```{r} | |
newcentroids <- findboxes(centroids, xcol = 'long', ycol='lat', | |
pad_point_x = 10, pad_point_y = 10, | |
xlim = c(-180,180), ylim=c(-60,60), | |
force=0.2, | |
maxiter = 1000) | |
newcentroids %>% | |
add_rownames("country") %>% | |
inner_join(flagfiles, by=c("country")) %>% | |
mutate(pngfile = paste0("./flags/",flag)) -> newflagfiles | |
apply(newflagfiles, | |
1, | |
function(x) | |
{img <- readPNG(x['pngfile']) | |
g <- rasterGrob(img, interpolate=TRUE) | |
lat <- as.numeric(x['y2']) | |
long <- as.numeric(x['x2']) | |
return(list(grob=g, long=long,lat=lat)) | |
}) -> newgrobs | |
gg2 <- gg + geom_point(data=newflagfiles, aes(x1,y1)) | |
gg2 <- gg2 + geom_segment(data=newflagfiles, aes(x1,y1,xend=x2,yend=y2)) | |
Reduce(addmap,newgrobs,gg2) | |
``` | |
## Use ggrepel with Force=0.8 to plot | |
```{r} | |
newcentroids <- findboxes(centroids, xcol = 'long', ycol='lat', | |
pad_point_x = 10, pad_point_y = 10, | |
xlim = c(-180,180), ylim=c(-60,60), | |
force=0.8, | |
maxiter = 1000) | |
newcentroids %>% | |
add_rownames("country") %>% | |
inner_join(flagfiles, by=c("country")) %>% | |
mutate(pngfile = paste0("./flags/",flag)) -> newflagfiles | |
apply(newflagfiles, | |
1, | |
function(x) | |
{img <- readPNG(x['pngfile']) | |
g <- rasterGrob(img, interpolate=TRUE) | |
lat <- as.numeric(x['y2']) | |
long <- as.numeric(x['x2']) | |
return(list(grob=g, long=long,lat=lat)) | |
}) -> newgrobs | |
gg2 <- gg + geom_point(data=newflagfiles, aes(x1,y1)) | |
gg2 <- gg2 + geom_segment(data=newflagfiles, aes(x1,y1,xend=x2,yend=y2)) | |
Reduce(addmap,newgrobs,gg2) | |
``` | |
## Use ggrepel with Force=1 to plot | |
```{r} | |
newcentroids <- findboxes(centroids, xcol = 'long', ycol='lat', | |
pad_point_x = 0.1, pad_point_y = 0.1, | |
boxsize = 10, | |
xlim = c(-180,180), ylim=c(-60,60), | |
force=1, | |
maxiter = 1000) | |
newcentroids %>% | |
add_rownames("country") %>% | |
inner_join(flagfiles, by=c("country")) %>% | |
mutate(pngfile = paste0("./flags/",flag)) -> newflagfiles | |
apply(newflagfiles, | |
1, | |
function(x) | |
{img <- readPNG(x['pngfile']) | |
g <- rasterGrob(img, interpolate=TRUE) | |
lat <- as.numeric(x['y2']) | |
long <- as.numeric(x['x2']) | |
return(list(grob=g, long=long,lat=lat)) | |
}) -> newgrobs | |
gg2 <- gg + geom_point(data=newflagfiles, aes(x1,y1)) | |
gg2 <- gg2 + geom_segment(data=newflagfiles, aes(x1,y1,xend=x2,yend=y2)) | |
Reduce(addmap,newgrobs,gg2) | |
``` |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment