1 Baby steps

1.1 CalculatoR

Write the following operations (results are in square brackets):

  1. \(\sqrt{(15)} * 14 - \frac{22}{4}\) [48.72177]
See solution
sqrt(15) *14 - 22/4
## [1] 48.72177
  1. \(\frac{\sqrt{7-\pi}}{3\ (45-34)}\) [0.05952372]
See solution
sqrt(7 - pi)/(3*(45 -34))
## [1] 0.05952372
  1. \(\frac{e^{(5-4)}}{1+e^{(5-4)}}\) [0.7310586]
See solution
exp(5-4)/(1+exp(5-4))
## [1] 0.7310586
  1. \(log(\frac{0.7}{1-0.5})* \sqrt{(\frac{20\times 3}{2})^5}\) [1658.641]
See solution
log(0.7/(1-0.5)) * sqrt(((20 *3)/2)^5)
## [1] 1658.641
  1. \(\frac{\sum_{n=1}^{10} n}{10}\) [5.5]
See solution
sum(1:10)/10
## [1] 5.5

Details:

  • Square root: sqrt()
  • \(e\): exp(1).
  • \(log\): log(x, base=a)
  • \(\pi\): pi

1.2 Vectors

  1. Create a vector x of length 7 containing only odd numbers
See solution
x = seq(1, 13, by=2)
  1. Create a vector y from x such that it includes the values \(\leq 3\) and those \(\geq 9\):
See solution
y = x[x <= 3|x >=9] 
  1. Create vector z from y such that it includes the values \(<\) \(M(y)\):
See solution
z = y[y < mean(y)] 
  1. Create this vector: on, on, on, on, on, off, off and name it v:
See solution
v = rep(c("on", "off"), c(5, 2))
  1. Create this vector A1, A2, B1, B2, C1, C2, D 1, D 2, A, B and name it h:
See solution
h = c(paste0("A", 1:2), paste0("B", 1:2), paste0("C", 1:2), 
      paste0("D", 1:2), LETTERS[1:2])
  1. From vector h, select only the elements containing number 1 and store them in vector g:
See solution
g = h[grepl("[1]", h)]
g
## [1] "A1" "B1" "C1" "D1"
  1. Replace all elements in h that contains A or B and a number with “!”:
See solution
gsub("[AB]+[0-9]", "!", h)
##  [1] "!"  "!"  "!"  "!"  "C1" "C2" "D1" "D2" "A"  "B"

1.3 Data frames

  1. Create a data frame with 60 subjects and two factor variables:
  • id: Subjects ids from 1 to 60 (factor)
  • light: Subjects’ light, with levels male, medium, low (factor, mind the order)
  • group: treatment vs. control (factor, mind the order)

light and group are crossed factors in a balanced design, so there are 10 subjects in each cell. Check the structure of the data set (hint: use tab())

See solution
dat = data.frame(id = paste0("sbj", 1:60), 
                 light = factor(rep(c("low", "medium", "high"), each=10), 
                              levels = c("high", "medium", "low")), 
                 group = factor(rep(c("control", "treatment"), each=30), 
                 levels = c("treatment", "control")))
# check 
table(dat$light, dat$group)
##         
##          treatment control
##   high          10      10
##   medium        10      10
##   low           10      10
  1. Add column growth to dat with response times drawn from a gamma distribution (use set.seed(999), and set shape = 1 in the function for generating the data)
See solution
set.seed(999)
dat$growth = rgamma(60, shape=1)
  1. Order the data frame by decreasing growth:
See solution
dat = dat[order(dat$growth, decreasing = T), ]
  1. Compute the mean and standard deviation of growth considering light * group. Save the results in two objects (mean_growth and sd_growth)
See solution
mean_growth = aggregate(growth ~ light * group, data = dat, mean)
sd_growth = aggregate(growth ~ light * group, data = dat, sd)
  1. Rename the last column of mean_growth and sd_growth in m_growth and sd_growth, respectively, without using manual indexing (e.g., colnames(mean_growth)[3])>
See solution
# indexing the position
colnames(mean_growth)[ncol(mean_growth)] = "m_growth"

# explicitly referring to the name of the column
names(sd_growth)[colnames(sd_growth) == "growth"] ="sd_growth"
  1. Merge mean_growth and sd_growth in summary_dat and order it by group:
See solution
summary_dat = merge(mean_growth, sd_growth, 
                    by = c("light", "group"))

summary_dat = summary_dat[order(summary_dat$group),]
summary_dat
##    light     group  m_growth sd_growth
## 2   high treatment 0.8584894 0.7382253
## 4    low treatment 0.9564785 0.9408343
## 6 medium treatment 0.8152060 0.9241339
## 1   high   control 1.0360285 0.7352210
## 3    low   control 1.6033103 1.3364729
## 5 medium   control 1.0229396 0.6119325

1.4 Plots

1.4.1 Base plots

  1. Pairwise plot of dat:
See solution
plot(dat)
  1. Plot growth according to group
See solution
plot(dat$growth ~ dat$group)
  1. Plot growth according to light
See solution
plot(dat$growth ~ dat$light)

1.4.2 ggplot

  1. Violin plot of growth according to light (hint: use geom_violin(trim=F):
See solution
library(ggplot2)
## 
## Caricamento pacchetto: 'ggplot2'
## Il seguente oggetto è mascherato da 'package:emoji':
## 
##     arrow
ggplot(dat, aes(x = light, y=growth)) + geom_violin(trim = F)
  1. Violin plot of growth according to light and group:
See solution
library(ggplot2)

ggplot(dat, aes(x = light, y=growth, fill=group)) + geom_violin(trim = F)

# also

ggplot(dat, aes(x = light, y=growth, color=group)) + geom_violin(trim = F)

Go wild with the plot options! Play with them 😃

2 Programming

2.1 Data manipulation

  1. Create a new column (foo) in dat following these guidelines:
  • growth \(\leq\) first quartile of growth: “A”
  • first quartile of growth \(<\) growth \(\leq\) third quartile of growth: “B”
  • growth \(>\) third quartile of growth: “A”

(hint: use the quantile() function)

The solution can be obtained with 2 different codes. Write them both.

See solution A
growth_q = quantile(dat$growth)

dat$foo = with(dat, 
               ifelse(growth <= growth_q[2], "A", 
                      ifelse(growth > growth_q[2] & growth <= growth_q[4], 
                             "B", 
                             "C")))
See solution B
growth_q = quantile(dat$growth)

dat$bar = character(nrow(dat))

for (i in 1:nrow(dat)) {
  if (dat[i, "growth"] <= growth_q[2]) {
    dat[i, "bar"] = "A"
  } else if (dat[i, "growth"] > growth_q[2] & dat[i, "growth"] <= growth_q[4]) {
    dat[i, "bar"] = "B"
  } else {
    dat[i, "bar"] = "C"
  }
}
  1. Create this data set:
data = data.frame(id = paste0("s", 1:100), 
                  condition = c(rep(c("A", "B", "C", "D"), each=25)), 
                  group = c(rep(c("treatment", "control"), each=50)), 
                  sex = c(rep(c("male", "female"), each=50)), 
                  rt = rgamma(100, shape=3))

Write the code for transforming all the columns identified as characters in factors. Two solutions are possible, write them both.

See solution A
if (any(sapply(data, is.character)) == TRUE) {
  data[, sapply(data, is.character) == T] = lapply(data[, sapply(data, is.character) == T], 
                                                 as.factor)
} else {
  data = data
}
See solution B
for (i in 1:ncol(data)) {
  if (is.character(data[,i]) == TRUE) {
    data[, i] = as.factor(data[ ,i])
  } else {
    data[ ,i] = data[ ,i]
  }
}

2.2 Functions

  1. Write the function my_mean() to compute the mean of a vector without using the mean() function (use the mean() function just to check whether you did it right)
See solution
set.seed(999)
my_mean = function(data) {
  m = sum(data)/length(data)
  return(m)
}

vec = rnorm(10)
my_mean(vec) == mean(vec)
## [1] TRUE
  1. Add a check step: If it is not an integer or a numeric vector, throws the error “STOP! I need integer or numeric vectors!”
See solution
my_mean = function(data) {
  if (is.integer(data) | is.numeric(data) == FALSE) {
    stop("STOP! I need integer or numeric vectors!")
  } else {
      m = sum(data)/length(data)
  }
    return(m)
}
# Use this cose to check
# vec = letters[1:10]
# my_mean(vec)
# 
# my_mean(as.factor(vec))
# 
# my_mean(as.logical(vec))
  1. Define the print method print.mean() for my_mean() that says “The mean of your vector is:”
See solution
print.mean = function(object) {
  cat("The mean of your vector is:", object)
  invisible(object)
}
  1. print.mean() only print objects of class my.mean, otherwise it throws the error “Sorry, I print only objects of class my.mean”
See solution
my_mean = function(data) {
  if (is.integer(data) | is.numeric(data) == FALSE) {
    stop("STOP! I need integer or numeric vectors!")
  } else {
      m = sum(data)/length(data)
      class(m) = "my.mean"
  }
    return(m)
}

print.mean = function(object) {
  if ((class(object) != "my.mean") == T) {
    stop("Sorry, I print only objects of class my.mean")
  } else {
      cat("The mean of your vector is:", object)
  invisible(object)
  }
}
# Use this code to check
# vec = rnorm(10)
# classic_m = mean(vec)
# 
# print.mean(classic_m)
# 
# my_m = my_mean(vec)
# print.mean(my_m)
  1. Write a function that computes the factorial of a number \(n! = (n-1) \times (n-2) \times \ldots 1\) (Two solutions are possible, check with function factorial()):
See solution A
my_factorial = function(number) {
  fact = 1 
  for( i in 1:number) {
  fact = fact * i
}
return(fact)
}

my_factorial(5) == factorial(5)
## [1] TRUE
See solution B
my_factorial = function(number) {
  fact = number * (number - 1)
  for (i in 2:(number-1)) {
  fact =  fact * (number-i)
  }
  return(fact)
}

my_factorial(5) == factorial(5)
## [1] TRUE

3 Shiny

Shiny set up:

install.packages("shiny")
library(shiny)

ui = fluidPage(
  [....]
)

server = function(input, output) {
  [....]
}

shinyApp(ui = ui, server = server)
  1. Using the template above, create a shiny app with Radio buttons with 4 choices (make them 4 Netflix series). The output is: “You choose X” (where x is the actual input).
See solution
ui = fluidPage(
  title = "What is your favorite series?", 
  radioButtons("the_choice", "Make your choice!", 
               choices = list("Squid game" = "Squid game",
                              "Black mirror" = "Black mirror", 
                              "The office" = "The office", 
                              "Modern family" = "Modern family")), 
  fluidRow(column(4, 
                   verbatimTextOutput("choice") ))

)
  
server = function(input, output) {
  output$choice = renderPrint({
    cat("You choose:", input$the_choice)
  })
}

shinyApp(ui, server)
  1. Use an action button “Show my choice!” to see the results (Hint: see the examples for eventReactive())
See solution
ui = fluidPage(
  title = "What is your favorite series?", 
  radioButtons("the_choice", "Make your choice!", 
               choices = list("Squid game" = "Squid game",
                              "Black mirror" = "Black mirror", 
                              "The office" = "The office", 
                              "Modern family" = "Modern family")), 
  
  fluidRow(column(4, 
                 actionButton("go", "Show my choice!" ) ), 
           column(4, 
                   verbatimTextOutput("choice") ))

)
  
server = function(input, output) {
  
  choice <- eventReactive(input$go, {
    cat("You choose:", input$the_choice )
  })

  output$choice = renderPrint({
    choice()
  })
}

shinyApp(ui, server)
  1. Create a 5th option with a text box that appears only if the 5-option (i.e., “Another show”) is selected:
See solution
ui = fluidPage(
  title = "What is your favorite series?", 
  radioButtons("the_choice", "Make your choice!", 
               choices = list("Squid game" = "Squid game",
                              "Black mirror" = "Black mirror", 
                              "The office" = "The office", 
                              "Modern family" = "Modern family", 
                              "Another show" = 5)),
  conditionalPanel(
        condition = "input.the_choice == '5'", 
  textInput("my_show", label = "My favorite show", value = "")),
  
  fluidRow(column(4, 
                 actionButton("go", "Show my choice!" ) ), 
           column(6, 
                   verbatimTextOutput("choice") ))

)
  
server = function(input, output) {
  
  choice <- eventReactive(input$go, {
    if (input$the_choice == 5) {
       cat("My favorite show is:", input$my_show )
    } else {
       cat("My favorite show is:", input$the_choice )
    }
  })

  output$choice = renderPrint({
    choice()
  })
}

shinyApp(ui, server)
  1. Create a shiny app to display the head of the data set chose by the users (stick with radio buttons) (you can use the data sets I used in my slides, but use mtcars instead of cars). The head can be seen only after an action button is clicked
See solution
ui = fluidPage( 
        radioButtons(inputId = "dataset",
                    label = "Choose a dataset:",
                    choices = list("rock" = 1, 
                                   "pressure" = 2, 
                                   "mtcars" = 3)), 
        fluidRow(column(4, 
                      actionButton("go", "Select dataset")), 
                 column(6, 
                   tableOutput("summary") ))
       
           )
        
server = function(input, output){        
    dataInput = eventReactive(input$go, { # here's the action for the button
      if(input$dataset == 1){ # call the input and its options with their label
        data <- rock
      } else if (input$dataset == 2 ){
        data <- pressure
      } else if (input$dataset == 3) {
        data <- mtcars
      } 
      
    } 
    )
    
    output$summary <- renderTable({
      data = dataInput()
      head(data)
    })
}

shinyApp(ui, server)

renderDataTable() combined with renderDataTable() would have been fine as well

  1. Use solution 2 for the action button and the data set selection (make sure to write a waiting message) and add a plot (hint: use sidebarLayout()). This time use renderDataTable()
See solution
ui = fluidPage(
   sidebarLayout(
    sidebarPanel(
      selectInput(inputId = "dataset",
                  label = "Choose a dataset:",
                  choices = list("rock" = 1, 
                                   "pressure" = 2,
                                   "mtcars" = 3)),

      actionButton("go", "Upload data")
      ),
    mainPanel(
      fluidRow(column(6, 
                    plotOutput(
        "graph"
      )  ), 
      column(4, 
            dataTableOutput(
        "summary"
      ) )
      )
      
    ) 
  )
)

server = function(input, output){
 values <- reactiveValues()
  dataInput <- reactive({
    if(input$dataset == 1){
      data <- rock
    } else if (input$dataset == 2 ){
      data <- pressure
    } else if (input$dataset == 3) {
      data <- mtcars
    }
  })
  observeEvent(input$go, { # Use the observeEvent function to make the UI and 
    values$data <- data.frame(dataInput()) # server communicate again
  })

  output$graph <- renderPlot({
    plot(values$data[, c(1:2)])
  })

  output$summary <- renderDataTable({
    values$data
  })
}

shinyApp(ui, server)
  1. Add the code to select two columns to be plotted and displayed:
See solution
ui = fluidPage(
   sidebarLayout(
    sidebarPanel(
      selectInput(inputId = "dataset",
                  label = "Choose a dataset:",
                  choices = list("rock" = 1, 
                                   "pressure" = 2,
                                   "mtcars" = 3)),

      actionButton("go", "Upload data"), 
          conditionalPanel(                    
        condition = "input.go >= '1'",   
        uiOutput("var1"),    
        uiOutput("var2"), 
        actionButton("select", "Select & Display")
      )
      ),
  mainPanel(
      fluidRow(column(6, 
                    plotOutput(
        "graph"
      )  ), 
      column(4, 
            dataTableOutput(
        "summary"
      ) )
      )
      
    ) 
  )
)

server = function(input, output){
 values <- reactiveValues()
  dataInput <- reactive({
    if(input$dataset == 1){
      data <- rock
    } else if (input$dataset == 2 ){
      data <- pressure
    } else if (input$dataset == 3) {
      data <- mtcars
    }
  })
  observeEvent(input$go, { 
    values$data <- data.frame(dataInput())
  })

  output$var1 <- renderUI({    
    nam <- colnames(values$data) 
    selectInput("var1", label = "Select x:",
                choices = c(nam), multiple = FALSE,
                selected = nam[1])
  })
  
    output$var2 <- renderUI({    
    nam <- colnames(values$data) 
    selectInput("var2", label = "Select y:",
                choices = c(nam), multiple = FALSE,
                selected = nam[2])
  })
  newdata <- observeEvent(input$select, 
                          { 
                            values$newdata <- values$data[c(input$var1, input$var2)]
                          })
  
  output$graph <- renderPlot({
    plot(values$newdata)
  })

  output$summary <- renderDataTable({
    values$newdata
  })
}

shinyApp(ui, server)