images as xaxis in R via LaTeX
library(rvest) | |
## GDP per capita, top 11 countries | |
n_countries <- 11 | |
url <- "https://en.wikipedia.org/wiki/List_of_countries_by_GDP_(nominal)_per_capita" | |
html <- read_html(url) | |
gdppc <- html_table(html_nodes(html, "table")[3])[[1]][1:n_countries, ] | |
## clean up; remove non-ASCII and perform type conversions | |
gdppc$Country <- gsub("Â ", "", gdppc$Country) | |
gdppc$Rank <- iconv(gdppc$Rank, "latin1", "ASCII", sub = "") | |
gdppc$Country <- iconv(gdppc$Country, "latin1", "ASCII", sub = "") | |
gdppc$`US$` <- as.integer(sub(",", "", gdppc$`US$`)) | |
## flag images (yes, this processing could be done neater, I'm sure) | |
## get the 200px versions | |
flags_img <- html_nodes(html_nodes(html, "table")[3][[1]], "img")[1:n_countries] | |
flags_url <- paste0("http://", sub("[0-9]*px", "200px", sub('\\".*$', "", sub('^.*src=\\"//', "", flags_img)))) | |
flags_name <- sub(".svg.png", ".png", sub(".*(Flag_of)", "\\1", flags_url)) | |
## download each of the flags into a directory | |
if (!dir.exists("flags")) dir.create("flags") | |
for (flag in seq_along(flags_url)) { | |
switch(Sys.info()[["sysname"]], | |
Windows = { | |
download.file(flags_url[flag], destfile = file.path("flags", paste0(flag, "_", flags_name[flag])), method = "auto", mode = "wb") | |
}, | |
Linux = { | |
download.file(flags_url[flag], destfile = file.path("flags", paste0(flag, "_", flags_name[flag]))) | |
}, | |
Darwin = { | |
print("Not tested on Mac. Use one of the above and find out?") | |
} | |
) | |
} | |
# /etc/ImageMagick-6/policy.xml | |
# <policy domain="coder" rights="none" pattern="PDF" /> | |
# <policy domain="coder" rights="read|write" pattern="PDF" /> | |
# https://stackoverflow.com/questions/42928765/convertnot-authorized-aaaa-error-constitute-c-readimage-453 | |
library(magick) | |
## load the images from filenames | |
npoints <- length(flags_name) | |
pics <- vector(mode = "list", length = npoints) | |
image.file <- file.path(getwd(), dir("flags", full.names = TRUE)) | |
image.file <- image.file[order(as.integer(sub("_.*", "", sub("^.*flags/", "", image.file))))] | |
for (i in 1:npoints) { | |
pics[[i]] <- image_read(image.file[i]) | |
} | |
names(pics) <- sub(".svg.png", "", sub(".*Flag_of_", "", image.file)) | |
names(pics)[8] <- "USA" | |
## create a dummy dataset | |
y <- gdppc$`US$` | |
x <- names(pics) | |
dat <- data.frame(x = factor(x, levels = names(pics)), y = y) | |
library(ggplot2) | |
## create the graph, as per normal now with @baptiste's adapted grob processing | |
## NB: #85bb65 is the color of money in the USA apparently. | |
gg <- ggplot(dat, aes(x = x, y = y / 1e3L, group = 1)) | |
gg <- gg + geom_bar(col = "black", fill = "#85bb65", stat = "identity") | |
gg <- gg + theme_minimal() | |
gg <- gg + scale_fill_discrete(guide = FALSE) | |
gg <- gg + theme(plot.background = element_rect(fill = "grey90")) | |
gg <- gg + labs(title = "GDP per capita", | |
subtitle = "Top 11 countries", | |
x = "", y = "\\$US/1000", ## escaping for LaTeX | |
caption = paste0("\\shortstack{\\vspace{-1em}\\scriptsize{Source: ", | |
gsub("_", "\\\\_", url), "}}")) ## escaping for LaTeX | |
## use tikzDevice and include graphicx in the preamble | |
library(tikzDevice) | |
options(tikzLatexPackages = c(getOption("tikzLatexPackages"), "\\usepackage{graphicx}\n")) | |
## rather than typing this out every time, make it a function | |
make_label <- function(labels, files, scale = 0.2, offset = "2em") { | |
paste0("\\shortstack{\\includegraphics[scale=", scale, "]{", | |
files, "}\\\\\\hspace{-", offset, | |
"}\\rotatebox[origin=rt]{45}{\\small{", labels, "}}}") | |
} | |
## make some room for the images and caption | |
gg <- gg + theme(axis.text.x = element_text(size = 5, | |
lineheight = 0.9, | |
vjust = -4), | |
plot.margin = unit(c(5.5, 5.5, 12, 5.5), "points")) | |
## this is where most of the LaTeX magic is happening - the labels | |
gg <- gg + scale_x_discrete(breaks = names(pics), | |
labels = make_label(sub(".png", "", names(pics)), image.file)) | |
## process the object with LaTeX and produce a PDF | |
tikz("xaxis.tex", standAlone = TRUE, width = 4, height = 4) | |
print(gg) | |
dev.off() | |
tools::texi2dvi("xaxis.tex", pdf = TRUE) | |
## convert the resulting PDF to a png using magick | |
image_read_pdf("xaxis.pdf") %>% | |
image_convert(format = "png") %>% | |
image_write("xaxis.png", density = 500) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment