Shiny: creating experimental blocks/trials

I am trying to create a (pseudo) Implicit Association Test as a practice using Shiny - given that it is difficult to measure accurate response latency, I will probably use the number of correct/incorrect answers here to compute the IAT scores.

However, it seems to be a little more difficult to create the program than I expected it to be. Though, admittedly , I am very new to Shiny (&R programming in general). I would appreciate your help.

My questions are:

  1. is there a way to create multiple pages - so for instance, participant needs to press a key on the keyboard to proceed into the next page/trial/block - I have tried it (codes attached below), but I think there might be better/more efficient way to do this.
  2. how do I randomly display one of the imported images on the GUI per trial..? Would there be a way to do so??
ui <- fluidPage(
  useShinyjs(),
  div(
    id = "introduction",
    titlePanel("Welcome"),
    br(),
    mainPanel(
      fluidRow(
        align = "center",
        h2("Introduction"),
        p("In this study you will complete an Implicit Association Test (IAT)
          in which you will be asked to sort images into groups as fast as you can.
          In addition to the IAT, there are some questions about your beliefs,
          attitudes, and opinions, and some standard demographic questions.
          This study should take about 10 minutes to complete."),
        br(),
        p("We thank you for being here!"),
        br(),
        actionButton("Continue", label = "Continue")
      )
      ),

  hidden(
    div(
      id = "general instruction",
      h3("Implicit Association Test"),
      p("In this experiment, you will use the 'E' or 'I' computer keys to categorize
items into groups as fast as you can. These are the four groups and the items that belong to each:"),
      br(),
      em("Caucasian"),
         img(src = "caucasian1.png", height = 100, width = 100),
         img(src = "caucasian2.png", height = 100, width = 100),
         img(src = "caucasian3.png", height = 100, width = 100),
         img(src = "caucasian4.png", height = 100, width = 100),
         img(src = "caucasian5.png", height = 100, width = 100),
         img(src = "caucasian6.png", height = 100, width = 100),
         br(),
         em("Asian"),
        img(src = "asian1.png", height = 100, width = 100),
        img(src = "asian2.png", height = 100, width = 100),
        img(src = "asian3.png", height = 100, width = 100),
        img(src = "asian4.png", height = 100, width = 100),
        img(src = "asian5.png", height = 100, width = 100),
        img(src = "asian6.png", height = 100, width = 100),
        br(),
        em("Math"),
      list("Geometry", "Algebra", "Computation", "Calculus", "Biology", "Statistics"),
      em("Non-Math"),
      list("History", "Arts", "Humanities", "Music", "Philosophy", "Literature"),
      br(),
p("there are five parts. The instructions change for most of the parts.
          Pay attention!"),
      br(),
actionButton("Continue2", label = "Continue"))
  )
)
)


server <- function(input, output) {
  formData <- reactive({
    data <- sapply(fields, function(x) input[[x]])
    data
  })
  observeEvent(input$Continue, {
    hide("introduction")
    show("general instruction")
    })
  observeEvent(input$Continue2, {
    hide("general instruction")
    show("block1")})
}

# Run the application
shinyApp(ui = ui, server = server)

Hi @lee11, it'd be great if these images came from a public url...that would make it easier for us run your app.

I'm not sure what you mean by imported image, but regardless, sample() will be your friend...to randomly sample one of the caucasian image filenames, you could do:

paste0("caucasian", sample(1:6, 1), ".png")

is there a way to create multiple pages - so for instance, participant needs to press a key on the keyboard to proceed into the next page/trial/block

shinyjs has been a great way to go about this for some time, but the new shiny.router package might be a better option -- https://appsilon.com/shiny-router-package/

1 Like

Hi @cpsievert, thank you for your reply.

I might have an additional question.

I have changed the images into a set of words: i.e.

stimuli_set <- data.frame(A= c("a", "b", "c", "d"), B = c("e", "f", "g", h")).

I have used the "sample" function to sample a word, but this has not been going well.

sample(stimuli_set, size = 1, replace = T)

The above code returns:

    A
1. a
2. b 
3. c
4.  d

while I would only like to get one alphabet from the stimuli_set. Would you happen to know how I could fix this problem?

Thank you

The first argument to sample() should be a vector, not a data.frame(). You could sample a row of the data frame this way:

row_ids <- seq_len(nrow(stimuli_set))
stimuli_set[sample(row_ids, 1, replace = T), ]

An easier way to do the same thing is to use dplyr::sample_n(stimuli_set, 1)

1 Like