Want to share your content on R-bloggers? click here if you have a blog, or here if you don't.
In a recent blog post I introduced Stefanie Posavec‘s Sentence Drawings. We created this ggplot2 rendition:
We left off weighing the aesthetics of the Sentence Drawing with information of quality visualizations. I asked others to think of ways to display the information and also hinted that I’d use Yihui’s animation package to show the fluid nature of the conversation. Jim Vallandingham stepped up with a D3 rendering of the Sentence Drawing (though not implemented in R as we’ve grown accustomed to with rCharts) that gives a mouse over of the dialogue (GitHub here). I too followed up with the animation version as seen in the video outcome and accompanying script below.
Click Here to view the html version.
If you likes what you see then have a lookyloo at the code below.
Getting Started
Installing Packages from GitHub and Turn Function
# install.packages("devtools") library(devtools) install_github(c('slidify', 'slidifyLibraries'), 'ramnathv', ref = 'dev') install_github("knitcitations", "cboettig") install_github(c("reports", "qdapDictionaries", "qdap"), "trinker") install_github("ggthemes", "jrnold") install.packages('scales') invisible(lapply(c("qdap", "ggplot2", "ggthemes", "scales", "grid"), require, character.only = TRUE)) turn_it <- function(dataframe, len.col, turn = -pi/2) { dat <- dataframe dat[, "turn"] <- rep(turn, nrow(dataframe)) dat <- within(dat, { facing <- pi/2 + cumsum(turn) move <- dat[, len.col] * exp(1i * facing) position <- cumsum(move) x2 <- Re(position) y2 <- Im(position) x1 <- c(0, head(x2, -1)) y1 <- c(0, head(y2, -1)) }) dat[, c("x1", "y1", "x2", "y2")] <- lapply(dat[, c("x1", "y1", "x2", "y2")], round, digits=0) data.frame(dataframe, dat[, c("x1", "y1", "x2", "y2")]) }
The Animation Code
library(animation) ## Prepping the data dat2b <- rajSPLIT dat2b$wc <- wc(rajSPLIT$dialogue) dat2b <- dat2b[!is.na(dat2b[, "wc"]), ] ## Reassign names to family affiliation dat2b[, "fam.aff"] <- factor(lookup(as.character(dat2b[, "fam.aff"]), levels(dat2b[, "fam.aff"])[1:3], qcv(Escalus, Capulet, Montague), missing = NULL)) ## Make dataframe with the beginning coordinates of each act beg_act <- do.call(rbind, lapply(with(turn_it(dat2b, "wc"), split(turn_it(dat2b, "wc"), act)), function(x) { x[1, qcv(act, x1, y1, x2, y2)] })) keys <- sapply(split(1:nrow(dat2b), dat2b[, "act"]), head, 1) factor(all.birds$birds) ani_dat <- turn_it(dat2b, "wc") yl <- range(ani_dat[, c("y1", "y2")]) xl <- range(ani_dat[, c("x1", "x2")]) ## An animation base function ani_sent <- function(i){ base <- ggplot(ani_dat[1:i, ], aes(x = x1, y = y1, xend = x2, yend = y2)) + geom_segment(aes(color=fam.aff), lineend = "butt", size=1) + guides(colour = guide_legend(override.aes = list(alpha = 1))) + theme_few() + scale_colour_few(name="Family\nAffiliation", drop = FALSE) + theme(axis.ticks = element_blank(), axis.text = element_blank(), axis.title= element_blank(), legend.position = c(.1, .85), legend.title.align = .5) + ggtitle("Romeo and Juliet Family\nAffiliation: Sentence Drawing") addon1 <- geom_text(data=beg_act[i >= keys,], aes(x = x1, y=y1, label = paste("Act", act)), colour = "grey25", hjust = -.1, size=5, face = "bold") addon2 <- geom_point(data=beg_act[i >= keys,], aes(x = x1, y=y1), size=2.3, colour = "grey25") base2 <- base + addon1 + addon2 info <- ani_dat[i, c("tot", "act")] base3 <- base2 + geom_rect(aes(xmin = -173, xmax = -79, ymin = -160, ymax = -110), fill="white", colour="grey75") + annotate("text", x = -150, y=-125, label = "ACT", colour="grey75", size=4, face = "bold") + annotate("text", x = -105, y=-125, label = "T.O.T.", colour="grey75", size=4, face = "bold") + annotate("text", x = -150, y=-145, label = as.character(info[2]), colour="grey75", size=4, face = "bold") + annotate("text", x = -105, y=-145, label = as.character(info[1]), colour="grey75", size=4, face = "bold") + xlim(xl) + ylim(yl) print(base3) } pp2 <- function(x=base, alph = .15){ for(i in 1:nrow(ani_dat)){ ani_sent(i) ani.pause() } } ## Plot it out <- file.path(getwd(), "sent3") ## Change this as needed saveVideo(pp2(), interval = 0.01, outdir = out, ffmpeg = "C:/Program Files (x86)/ffmpeg-latest-win32-static/ffmpeg-20130306-git-28adecf-win32-static/bin/ffmpeg.exe") saveHTML(pp2(), autoplay = FALSE, loop = FALSE, verbose = FALSE, outdir = out, single.opts = "'controls': ['first', 'previous', 'play', 'next', 'last', 'loop', 'speed'], 'delayMin': 0")
For more on intro to animations see, this blog post.
< size="1">*Blog post created using the reports package< >
R-bloggers.com offers daily e-mail updates about R news and tutorials about learning R and many other topics. Click here if you're looking to post or find an R/data-science job.
Want to share your content on R-bloggers? click here if you have a blog, or here if you don't.