• Publicado: 20 Dec 2016

  • Archivado en: datascience, shiny, app, mba, r-english

Shiny App for MBA Interviews

A couple of weeks ago I attended some interviews as part of my process for admission into an MBA program. While most candidates would pore over the possible questions and then try to teach them to a third party to help them with a mock interview, I decided to expedite the process by building a shiny app in R.

In the name of helping anyone out there who knows R and is applying to an MBA (I know it is probably very few people), here is the code and a simple explanation of my workflow.

Workflow

First, you will need an excel with all the possible questions to ask. I compiled one here. You place this excel in the folder with the ui.R and server.R files. When a button is pressed on the app (the “score”), the shiny app will export a very small text file into that folder. This file will be separated by pipes and have 6 columns and one row: each indicating what question and school it is and the subjective score given by the interviewer to the question.

When you want to analyze the results, you simply import each file and rbind them to have a nifty data.frame. I’ll also leave the code to do this later on.

Now, on to the code.

server.R

Change it as you wish. There is a timer, that will indicate when time is running more the standard the interview suggests.

library(shiny)
library(readxl)
library(shinyjs)
library(dplyr)
d <- read_excel("qs.xlsx")
jsResetCode <- "shinyjs.reset = function() {history.go(0)}"

shinyServer(function(input, output, session) {
  EventTime <- Sys.time()
  
  qqt <- reactive({
    if(input$response=="To interviewer"){
      d <- d %>% filter(RESPONSE=="To Interviewer")
    }else{
      d <- d %>% filter(RESPONSE=="To applicant")
    }
    
    qs <- d$Q
    qn <- sample(row.names(d),1)
    qr <- qs[as.numeric(qn)]
    if(grepl(pattern = "(\\[SCHOOL\\])", x = qr)){
      qr <- gsub(pattern = "(\\[SCHOOL\\])", replacement = input$school, x = qr)
    }
    as.character(paste0("Q",qn,": ",qr))
  })
  
  output$qqt2 <- renderText({ 
    txt <- qqt()
    txt 
    })
 
  output$eventTimeRemaining <- renderUI({
    invalidateLater(1000, session)
    tm <- as.numeric(round(difftime(
      Sys.time(), EventTime, units = 'secs')))
    
    if(tm<input$NormalTime*60){
    HTML(paste0("Elapsed time: ", ifelse(tm<60, paste0(tm, " seconds."), 
                                    paste0(tm%/%60, ":", tm%%60, " mins."))))
    }else{
      HTML(paste0('<p style="color:#9f1317;"><strong>',paste0("Time-up!! (", ifelse(tm<60, paste0(tm, " seconds)."), 
                                      paste0(tm%/%60, ":", tm%%60, " mins).")))),'</strong></p>')
    }
  })
  
  observeEvent(input$reset, {
    shinyjs::reset("qqt")
  })
  
  observeEvent(input$reset_button, {js$reset()})  
  
  observeEvent(input$submit, {
    tm <- as.numeric(round(difftime(
      Sys.time(), EventTime, units = 'secs')))
    
    nq <- substr(as.character(qqt()), start = 1, 
           stop = gregexpr(pattern = ":", qqt())[[1]][1]-1)
    
    dtm <- data.frame("School" = input$school, 
                       "Seconds" = tm,
                       "Question" = qqt(),
                       "Number" = nq,
                       "Fluid" = input$score1, 
                       "Content" = input$score2,
                      "Hour" = Sys.time(),
                      "Date" = Sys.Date(),
                      "Type" = "New")
    
    nm <- paste0(Sys.Date(),
                 gsub(pattern = ":",
                      replacement = "_",
                      x = substr(Sys.time(),12,19)))
    
    write.table(dtm, file = paste0("Interviews_", nm, ".txt"), 
                sep = "|", row.names = FALSE)
  })
  
})

ui.R

library(shiny)
library(shinyjs)
jsResetCode <- "shinyjs.reset = function() {history.go(0)}"

shinyUI(fluidPage(
  useShinyjs(),
  # Application title
  titlePanel("MBA Interview Questions"),

  # Sidebar with a slider input for number of bins
  sidebarLayout(
    sidebarPanel(
      sliderInput("NormalTime", "Minutes per response:",
                  min = 0, max = 60, value = 2
      ),
      selectInput("response", "Question type:",
                  c("To applicant","To interviewer")),
          # you can select which schools here...        
      selectInput("school", "School:",
                  c("School 1","School 2")),
      HTML('<h4> Typical Methods for Behavioural Questions </h4> <br/>
           <h4> <strong> STAR: </strong><h4> <br/>
          <strong>S</strong>ituation: indentify the situation <br/>
          <strong>T</strong>ask: identify task or project <br/>
          <strong>A</strong>ction: describe what you did <br/>
          <strong>R</strong>esult: summarize the results <br/>
          <h4> <strong> CAR: </strong><h4> </ br>
          <strong>C</strong>ontext: describe the context <br/>
           <strong>A</strong>ction: describe what you did <br/>
           <strong>R</strong>esult: summarize the results <br/>
           ')
    ),
    mainPanel(
      HTML('<h1> Question </h1>'),
      hr(),
      h2(textOutput('qqt2')),
      uiOutput('eventTimeRemaining'),
      hr(),
      sliderInput("score1", "Fluidity and Security:",
                  min = 0, max = 10, value = 5
      ),
      sliderInput("score2", "Content:",
                  min = 0, max = 10, value = 5
      ),
      extendShinyjs(text = jsResetCode),
      actionButton("reset_button", "New Question"),
      actionButton("submit", "Score")
    )
  )
))

Import to analyze

This is the code used to import all of the files starting with “Interviews” from the folder.

LoadManyTxt <- function(regex, separator = "|"){
  a <- list.files()[grepl(pattern = regex,
                          list.files())]
  datos <- NULL
  #import
  for(i in 1:length(a)){
    temp <- as.data.frame(read.delim(
      a[i], sep = separator,
      stringsAsFactors = FALSE))
    
    print(paste0("Importing... ", a[i]))
    if(length(temp)==6){
      temp$Hora <- NA
      temp$Fecha <- NA
      temp$Tipo <- "Previous"
    }
    datos <- rbind.data.frame(datos, temp)
    print(paste("Data: ", length(datos[,1])," rows"))
  }
  return(datos)
}
# when in the folder, just do...
d <- LoadManyTxt("Interviews_")

It might seem intense, but this definitely saved me a few hours. As for the outcome of the interviews, I was invited to join two of my school choices, so it all worked out! Although, having gone through the experience, I think the old mantra: “be yourself” is probably better advice than using this app, so use at your own risk!