This is the R code I used to create the PNGs which are afterwards put together with ffmpeg into a clip (check ’em out). I am just commenting on the programmatic aspects. In a separate article I will write about how ggplot2 is used and how ffmpeg turns the PNGs into a clip.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
library(ggplot2) library(grid) # create data frame with column d keeping the date and a and b the quotes data <- data.frame(d = stocks$d, a = stocks$rheinmetall, b = stocks$thyssenkrupp) # get rid of rows where a quote is missing data <- na.omit(data) # calls the below defined function # creates 1000 PNGs (from 0 to 999) sized 1380 x 720 pixels for every # availabe record (second parameter = 3 would mean every third record f.x. # 0.8 is the alpha value and 2 the size for the scatterplot points shift_plot_data(data, 1, 999, 1380, 720, 0.8, 2) |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 |
# pops first/oldest element of column b and # pushes NA to the end. columns d and a stay # untouched. shift_data_col_b <- function(data) { d <- data$d a <- data$a b <- data$b b <- c(b[-1],NA) return(data.frame(d=d,a=a,b=b)) } # creates the scatter plot for the current data frame content. create_scatterplot <- function(alpha, psize, x_min, x_max, y_min, y_max) { s <- ggplot(data,aes(a,b,color=format(d,"%Y"))) s <- s + geom_point(alpha=alpha, size=psize) s <- s + geom_path(alpha=alpha) s <- s + scale_x_continuous(name="", limits=c(0,x_max)) s <- s + scale_y_continuous(name="", limits=c(0,y_max)) s <- s + scale_color_discrete(name="") return(s) } # creates the two line charts. create_chart <- function(i, y_min, y_max) { c <- ggplot(data = data, title="", ymin = y_min, ymax = y_max) c <- c + geom_line(aes(d,a,color="A")) c <- c + geom_line(aes(d,b,color="B")) c <- c + theme(legend.position = c(0.9,0.9), legend.title = element_text(size=20), legend.text = element_text(size=12)) c <- c + scale_y_continuous(name="", limits=c(0,y_max)) c <- c + scale_x_date(name="") c <- c + scale_color_manual(i, values=c("darkgreen","darkblue"), breaks=c("A","B")) return(c) } # plots both charts next to each other and saves the output in a PNG plot_data <- function(data, i, s,c, w,h) { # %+% is a ggplot2 operator that updates the underlying # data frame of a ggplot2 object s <- s %+% data c <- c %+% data png(sprintf("proj/image%03d.png",i), width=w, height=h) pushViewport(viewport(layout = grid.layout(1,2))) print(c, vp=viewport(layout.pos.row = 1, layout.pos.col=1)) print(s, vp=viewport(layout.pos.row = 1, layout.pos.col=2)) dev.off() } # prepares the data frame for processing and invokes the plotting shift_plot_data <- function(data,step, N, w, h, alpha, psize) { a_max = max(data$a) b_max = max(data$b) a_min = min(data$a) b_min = min(data$b) # the idea here is to make sure that the stock with the highes # quote is mapped against the y axis of the scatter plot because # it will determine the hight of the line chart. Then I can make # sure that both charts have the same Y-axis to increase the # visual comparability. if(a_max > b_max) { names(data) = c("d","b","a") s_x_max = b_max s_x_min = b_min s_y_max = a_max s_y_min = a_min } else { s_x_max = a_max s_x_min = a_min s_y_max = b_max s_y_min = b_min } c_min = min(a_min, b_min) c_max = max(a_max, b_max) # repeat N+1 times for(i in 0:N) { j <- i * step s <- create_scatterplot(alpha, psize, s_x_min, s_x_max, s_y_min, s_y_max) c <- create_chart(j, c_min, c_max) plot_data(data, i, s,c, w,h) # shift column b 'step'-times before plotting again for(k in 1:step) { data <- shift_data_col_b(data) } } } |
If this article was helpful to you or you just enjoyed it – then don’t hesitate to leave a comment or share it using the links below this box (that would be uber-awesome)! If not – then you’re welcome to tell me what could be improved? Maybe you even have a suggestion for a new article?
– Thanks, Raffael
I want to be smart as you. :)