Reply To: Randomizing trials, with 1/5 of trials followed by a comprehension question

PennController for IBEX Forums Support Randomizing trials, with 1/5 of trials followed by a comprehension question Reply To: Randomizing trials, with 1/5 of trials followed by a comprehension question

#9580
Jeremy
Keymaster

1. I imagine you’ll have the 90 conversations listed in the CSV table, and that you’ll have a column that indicates which category each conversation falls into. I’ll assume you name that column category with the possible values A, B, C, D, E and F.

I’m not sure what you mean by “taken out”/”eliminated”: should those 30 items just never appear at all, in any form, in your experiment? Or should they still be included in the experiment, but just without a comprehension question, while the other 60 trials will indeed have a comprehension question? The solutions are significantly different depending on which of these two options you mean to implement

If it’s the former, then you just need to add a spin to the earlier method: instead of using a single array of 60 entries with 12 trues vs 48 falses, you’ll want to use 6 arrays (one per category) each with 5 falses and the rest of entries set to true. Then you can use the category column in newTrial to look up the appropriate array:

arraysTrialQ = {
  A: [...Array(20)].map((v,i)=>i>4),
  B: [...Array(20)].map((v,i)=>i>4),
  C: [...Array(15)].map((v,i)=>i>4),
  D: [...Array(15)].map((v,i)=>i>4),
  E: [...Array(10)].map((v,i)=>i>4),
  F: [...Array(10)].map((v,i)=>i>4),
}
fisherYates(arraysTrialQ.A)
fisherYates(arraysTrialQ.B)
fisherYates(arraysTrialQ.C)
fisherYates(arraysTrialQ.D)
fisherYates(arraysTrialQ.E)
fisherYates(arraysTrialQ.F)

Template("ContextBank.csv" , row =>
  newTrial("trial",
    // ...
    ...(arraysTrialQ[row.category].pop() == true? [
      newText("target2", row.question)
      // ...

If, on the other hand, you want to discard them altogether, things are quite different. You could insert the value from the category column in the trial’s label, so you have the ability to discriminate between them when controlling your sequence (ie. newTrial("trial-"+row.context,). Then you could then use the custom function pick to draw the desired number of trials from each category:

aTrials = randomize("trial-A")
bTrials = randomize("trial-B")
cTrials = randomize("trial-C")
dTrials = randomize("trial-D")
eTrials = randomize("trial-E")
fTrials = randomize("trial-F")

Sequence(
  "intro", "practice", 
  pick(aTrials,15), // 15 out of 20
  pick(bTrials,15), // 15 out of 20
  pick(cTrials,10), // 10 out of 15
  pick(dTrials,10), // 10 out of 15
  pick(eTrials, 5), //  5 out of 10
  pick(fTrials, 5), //  5 out of 10
  "send", "end"
)

2. Note that if you assign 5 falses to the E and F trials, you will effectively end up with all of them being assigned false, as you can easily see from the piece of code I give above—maybe you’re fine with that, but I wanted to bring your attention to it

You can indeed use a method similar to the one above, using arrays of trues and falses.

optionsCategories = {
  A: ["option1a","option2a","option3a"],
  B: ["option1b","option2b","option3b"],
  C: ["option1c","option2c","option3c"],
  D: ["option1d","option2d","option3d"],
  E: ["option1e","option2e","option3e"],
  F: ["option1f","option2f","option3f"]
}
arraysTrialOptions = {
  A: [...Array(15)].map((v,i)=>i>4),
  B: [...Array(15)].map((v,i)=>i>4),
  C: [...Array(10)].map((v,i)=>i>4),
  D: [...Array(10)].map((v,i)=>i>4),
  E: [...Array(5)].map((v,i)=>i>4),
  F: [...Array(5)].map((v,i)=>i>4),
}
fisherYates(arraysTrialOptions.A)
fisherYates(arraysTrialOptions.B)
fisherYates(arraysTrialOptions.C)
fisherYates(arraysTrialOptions.D)
fisherYates(arraysTrialOptions.E)
fisherYates(arraysTrialOptions.F)

Template("ContextBank.csv" , row =>
  newTrial("trial-"+row.category,
    // ...
    newVar("trueFalseOption").global().set( v=>arraysTrialOptions[row.category].pop() )
    ,
    newScale("answer", "answer1", "answer2")
      .label(0, optionsCategories[row.category][0] ) // always use the same first answer
      .label(1, (optionsCategories[row.category][trueFalseOption==true ? 1 : 2]) )
      .center()
      .button()
      // ...
  )
  .log("trueFalseOption", getVar("trueFalseOption"))
)

Re. questions a/b, I think the codes in this post sort of answer them already but I invite you to read the documentation about how labels and Template work, and this tutorial page on using a table. As you can see, I cannot give one general answer to these questions, as it all depends on how specifically you want to address the other questions, but you can answer them once you know how generating trials from a table and referencing them using their label in Sequence works

Jeremy