But before I show you how I did it, here’s the scenario for Brazil given how the US race finished:

So how was this quick hack app done…?

Trying out the new Shiny interactive stats app builder from the RStudio folk has been on my to do list for some time. It didn’t take long to realise that an interactive race scenario builder would provide an ideal context for trying it out. There are essentially two (with a minor middle third) steps to a Shiny model:

- work out the points difference between VET and ALO for all their possible points combinations in the US Grand Prix;
- calculate the points difference going into the Brazilian Grand Prix;
- calculate the possible outcomes depending on placements in the Brazilian Grand Prix (essentially, an application of the algorithm I did in the original post).

The Shiny app requires two bits of code – a UI in file ui.R, in which I define two sliders that allow me to set the actual (or anticpated, or possible;-) race classifications in the US for Vettel and Alonso:

library(shiny) shinyUI(pageWithSidebar( # Application title headerPanel("F1 Driver Championship Scenarios"), # Sidebar with a slider input for number of observations sidebarPanel( sliderInput("alo", "ALO race pos in United States Grand Prix:", min = 1, max = 11, value = 1), sliderInput("vet", "VET race pos in United States Grand Prix:", min = 1, max = 11, value = 2) ), # Show a plot of the generated model mainPanel( plotOutput("distPlot") ) ))

And some logic, in file server.R (original had errors; hopefully now bugfixed…) – the original “Paths to the Championship” unpicks elements of the algorithm in a little more detail, but basically I figure out the points difference between VET and ALO based on the points difference at the start of the race and the additional points difference arising from the posited finishing positions for the US race, and then generate a matrix that works out the difference in points awarded for each possible combination of finishes in Brazil:

library(shiny) library(ggplot2) library(reshape) # Define server logic required to generate and plot a random distribution shinyServer(function(input, output) { points=data.frame(pos=1:11,val=c(25,18,15,12,10,8,6,4,2,1,0)) points[[1,2]] a=245 v=255 pospoints=function(a,v,pdiff,points){ pp=matrix(ncol = nrow(points), nrow = nrow(points)) for (i in 1:nrow(points)){ for (j in 1:nrow(points)) pp[[i,j]]=v-a+pdiff[[i,j]] } pp } pdiff=matrix(ncol = nrow(points), nrow = nrow(points)) for (i in 1:nrow(points)){ for (j in 1:nrow(points)) pdiff[[i,j]]=points[[i,2]]-points[[j,2]] } ppx=pospoints(a,v,pdiff,points) winmdiff=function(vadiff,pdiff,points){ win=matrix(ncol = nrow(points), nrow = nrow(points)) for (i in 1:nrow(points)){ for (j in 1:nrow(points)) if (i==j) win[[i,j]]='' else if ((vadiff+pdiff[[i,j]])>=0) win[[i,j]]='VET' else win[[i,j]]='ALO' } win } # Function that generates a plot of the distribution. The function # is wrapped in a call to reactivePlot to indicate that: # # 1) It is "reactive" and therefore should be automatically # re-executed when inputs change # 2) Its output type is a plot # output$distPlot <- reactivePlot(function() { wmd=winmdiff(ppx[[input$vet,input$alo]],pdiff,points) wmdm=melt(wmd) g=ggplot(wmdm)+geom_text(aes(X1,X2,label=value,col=value)) g=g+xlab('VET position in Brazil')+ ylab('ALO position in Brazil') g=g+labs(title="Championship outcomes in Brazil") g=g+ theme(legend.position="none") g=g+scale_x_continuous(breaks=seq(1, 11, 1))+scale_y_continuous(breaks=seq(1, 11, 1)) print(g) }) })

To run the app, if your server and ui files are in some directory `shinychamp`, then something like the following should et the Shiny app running:

library(shiny) runApp("~/path/to/my/shinychamp")

You can find the code on github here: F1 Championship 2012 – scenarios if the race gets to Brazil…

Unfortunately, until a hosted service is available, you’ll have to run it yourself if you want to try it out…

Disclaimer: I’ve been rushing to get this posted before the start of the race… If you spot errors, please shout!

]]>