Skip to content

Instantly share code, notes, and snippets.

@petehamilton
Last active February 8, 2018 17:43
Show Gist options
  • Save petehamilton/1f3dbfa7da4adddd61e7 to your computer and use it in GitHub Desktop.
Save petehamilton/1f3dbfa7da4adddd61e7 to your computer and use it in GitHub Desktop.
Plot GoCardless Customers by Location
# Execute with: R --slave -f draw.r
library(maps)
library(mapdata)
library(foreach)
library(doParallel)
# Use the GoCardless font
par(family="Gotham-Book")
# Set colours
gocardless_blue = rgb(0.31,0.57,0.85)
gocardless_blue_translucent = rgb(0.31,0.57,0.85,0.1)
gocardless_dark_grey = rgb(0.298, 0.308, 0.394)
gocardless_dark_red = rgb(0.753, 0.361, 0.361)
# Set variables
width = 2000
height = 3000
output_directory = "/Users/petehamilton/projects/gocardless-map/output/gc-customers"
# Initialize parallel
cl <- makeCluster(detectCores() - 1)
registerDoParallel(cl, cores = detectCores() - 1)
# Read in the data
all_customers <- read.csv("/Users/petehamilton/projects/gocardless-map/data/customers-export.csv", header = TRUE)
# Make dates actual dates rather than strings (for comparison)
all_customers$date <- as.Date(as.character(all_customers$date),format="%Y-%m-%d")
# Get a list of all days from first to last customer
first_record = head(all_customers, 1)
last_record = tail(all_customers, 1)
all_days = seq(from=as.Date(first_record$date), to=as.Date(last_record$date), "days")
# Helper functions
draw_map <- function(border_color) {
map('worldHires', c('UK', 'Ireland', 'Isle of Man','Isle of Wight'), xlim=c(-11,3), ylim=c(49,60.9), fill=FALSE, col=border_color, mar=rep(1,4))
}
plot_customers <- function(customers, point_color, point_size_cex) {
points(customers$lon,customers$lat, col=point_color, pch=20, cex=point_size_cex)
}
set_title <- function(text, color) {
title(text, col.main=color)
}
print(paste("Num. Customers:", nrow(all_customers)))
print(paste("Total Days:", length(all_days)))
main_frame_count = length(all_days)
foreach(i = 1:main_frame_count, .packages = c("maps","mapdata")) %dopar% {
setwd(output_directory)
png(sprintf("frame_%06d.png", i), height=height, width=width, pointsize = 80)
# Split customers added prior to and on the current date
historic_customers <- all_customers[all_customers$date < all_days[i],]
new_customers <- all_customers[all_customers$date == all_days[i],]
draw_map("white")
plot_customers(historic_customers, gocardless_blue_translucent, 0.2)
plot_customers(new_customers, gocardless_dark_red, 0.3)
set_title(format(all_days[i], format="%Y-%m-%d"), gocardless_blue)
dev.off(dev.cur())
}
final_frame_count = 60 # 2s @ 30fps
foreach(i = 1:final_frame_count, .packages = c("maps","mapdata")) %dopar% {
setwd(output_directory)
png(sprintf("frame_%06d.png", main_frame_count + i), height=height, width=width, pointsize = 80)
opacity = i/final_frame_count
draw_map(rgb(0.31,0.57,0.85, opacity))
plot_customers(all_customers, gocardless_blue_translucent, 0.2)
set_title("GoCardless", rgb(0.31,0.57,0.85, opacity))
dev.off(dev.cur())
}
stopCluster(cl)
# Then in the images dir:
# ffmpeg -r 30 -i frame_%06d.png -b:v 2048k customer-growth.mpg
# avconv -f image2 -i %06d.png -c:v h264 -crf 1 -r 30 out.mpg
# For making a .mov, I found I needed to change a few things:
# See http://superuser.com/questions/820134/why-cant-quicktime-play-a-movie-file-encoded-by-ffmpeg
# ffmpeg -f image2 -r 30 -i frame_%06d.png -vcodec libx264 -pix_fmt yuv420p out.mov
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment