Skip to main content

Decipher Support

All the topics, resources needed for Decipher.

FocusVision Knowledge Base

Basic and Advanced Shuffling

Overview

Shuffling survey elements is a common task. To maintain consistency across the respondents' entire experience, you may also need to shuffle elements in the same order as they were previously shown. 

Basic Shuffling

To shuffle a question's elements, add the shuffle="rows,cols,choices,groups" attribute to the question tag.

<checkbox label="Q1" atleast="1" shuffle="rows">
    <title>Please select items you're familiar with.</title>
    <row label="r1">Item 1</row>
    <row label="r2">Item 2</row>
    <row label="r3">Item 3</row>
    <row label="r4">Item 4</row>
</checkbox>

shuffleBy

To shuffle a question's elements in the same order as a previous question, use the shuffleBy="QUESTION_LABEL" attribute.

<radio label="Q2" shuffle="rows" shuffleBy="Q1" rowCond="Q1[row]">
    <title>Which one is your favorite?</title>
    <row label="r1">Item 1</row>
    <row label="r2">Item 2</row>
    <row label="r3">Item 3</row>
    <row label="r4">Item 4</row>
</radio>

To use the shuffleBy attribute, the question's shuffled elements must be exactly the same as the original question. More often than not, the question's elements aren't the same and you will need to manually set the shuffle order.

Tip: You can shuffle rows and columns in the same question (e.g.,shuffle="rows,cols"), but shuffleBy will not stack this way (e.g.,shuffleBy="Q1,Q2" is invalid). To use shuffleBy, the target question must contain the same elements as the question by which to shuffle.

rowShuffle

It is also possible to dictate how question rows are shuffled. Use the rowShuffle attribute to specify the permutations for any shuffling you have applied to question rows (i.e., flip, rflip, rotate, reverse-rotate, rrotate).

Advanced Shuffling

When it's necessary to manually shuffle question elements, you can use the shuffled element's order attribute. This will return a list containing the shuffle order

In the following example, Q2 is shuffled in the same order as Q1.

<checkbox label="Q1" atleast="1" shuffle="rows">
    <title>Please select items you're familiar with.</title>
    <row label="r1">Item 1</row>
    <row label="r2">Item 2</row>
    <row label="r3">Item 3</row>
    <row label="r4">Item 4</row>
</checkbox>
<suspend/>

<exec>Q2.rows.order = Q1.rows.order</exec>
<radio label="Q2" shuffle="rows" rowCond="Q1[row]">
    <title>Which one is your favorite?</title>
    <row label="r1">Item 1</row>
    <row label="r2">Item 2</row>
    <row label="r3">Item 3</row>
    <row label="r4">Item 4</row>
</radio>

Using <exec> blocks and Python code, you can modify the shuffle order for any shuffled element.

Obtaining the Shuffle Order

The order attribute will provide you with access to the shuffle order for any group of shuffled elements.

The rows and columns in the question below, Q1, are being shuffled.The following is a table showing the various ways to access the shuffle order:

dec_basic_and_advanced_shuffling_001.png

Python Code Value
Q1.rows.order [[Q1.r1], [Q1.r3], [Q1.r2], [Q1.r4]]
Q1.cols.order [[Q1.c3], [Q1.c1], [Q1.c4], [Q1.c2]]
[x.index for x in Q1.rows.order] [0, 2, 1, 3]
[x.label for x in Q1.cols.order] ['c3', 'c1', 'c4', 'c2']
[x.text for x in Q1.rows.order] ['1', '3', '2', '4']
Q1.cols.order[1].text == "1" True

The order attribute returns a list of objects relative to the shuffled items. Using this list, you can easily create logic to set the shuffle order to fit the needs of your project.

Specifying the Shuffle Order

Setting the shuffle order for elements can be done by setting the value of the order attribute. Keep in mind that the system uses the index value for each shuffled item when setting shuffle order.

For example, given a shuffled question with 4 rows ("r1" - "r4"), you can set the shuffle order in the following ways:

Python Code Resulting Order
Q1.rows.order = Q0.rows.order Q0's row order
Q1.rows.order = Q0.cols.order Q0's col order
Q1.rows.order = Q0.choices.order Q0's choice order
Q1.rows.order = [0, 1, 2, 3] Ascending
Q1.rows.order = [0, 1, 2, 3, 4, 5, 6] Ascending
Q1.rows.order = [0] Ascending
Q1.rows.order = [Q1.r1, Q1.r2, Q1.r3, Q1.r4] Ascending
Q1.rows.order = [3, 2, 1, 0] Descending
Q1.rows.order = [6, 5, 4, 3, 2, 1, 0] Descending
Q1.rows.order = [Q1.r4, Q1.r3, Q1.r2, Q1.r1] Descending
Q1.rows.order = Q1.rows[::-1] Descending
Q1.rows.order = [3] "r4", "r1", "r2", "r3"
Q1.rows.order = [1, 2] "r2", "r3", "r1", "r4"
Q1.rows.order = Q1.rows.order Random (unnecessary)
Q1.rows.order = random.sample(xrange(4), 4) Random (unnecessary)
random.shuffle(Q1.rows.order) Random (unnecessary)

The table above illustrates that there are many ways to approach setting the shuffle order. Don't forget that you can set randomize="0" on any element to keep it in the same position and prevent it from being shuffled.

For example, if there is an exclusive option that should always remain on the bottom of the list, set randomize="0" on the element and it will remain in its anchored position.

<exec>Q1.rows.order = Q0.rows.order</exec>
<checkbox label="Q1" atleast="1" shuffle="rows">
    <title>Which items are you aware of?</title>
    <row label="r1">Item 1</row>
    <row label="r2">Item 2</row>
    <row label="r3">Item 3</row>
    <row label="r4">Item 4</row>
    <row label="r5" exclusive="1" randomize="0">None of the above</row>
</checkbox>

Recording the Shuffle Order

The order for all shuffled elements can be found in the "Random Order" file located in the "Tracking Files" section of the data downloads.

dec_basic_and_advanced_shuffling_002.png

You can also create virtual number question to track the shuffle order for questions individually. For example:

<radio label="Q1" shuffle="rows">
    <title>Please select one item.</title>
    <row label="r1">Item 1</row>
    <row label="r2">Item 2</row>
    <row label="r3">Item 3</row>
    <row label="r4">Item 4</row>
</radio>

<number label="Q1_ROW_ORDER" size="1" onLoad="copy('Q1', rows=True)">
    <title>Q1 Row Order</title>
    <virtual>
assignRandomOrder('Q1', 'rows')
    </virtual>
</number>

Note: Since this is a virtual question, it can be added to your project at any time.

In the example above, the function assignRandomOrder("Q1", "rows") creates an additional table in the report that tracks the order of each row item. Notice that the onLoad="copy(...)" mutator is used to load the same rows from Q1 into Q1_ROW_ORDER. For example, if the rows were shuffled in descending order, then the values for ("r1", "r2", "r3", "r4") would be (4, 3, 2, 1).

Here's what the Q1_ROW_ORDER table may look like for a single respondent:

dec_basic_and_advanced_shuffling_003.png

The table above indicates that this respondent's shuffle order was ("r1", "r2", "r4", "r3").

In addition to the function, assignRandomOrder, the function getRandomOrder is available too. This will return a list of labels representing the shuffle order for the question.

Calling getRandomOrder("Q1", "rows") for the respondent above will return the list, ["r1", "r2", "r4", "r3"].

Tip: As demonstrated in the examples below, you can also use the assignRandomOrder function to track the way in which questions were shuffled within a <block> tag.

Examples

Here are a few examples to demonstrate some of the advanced shuffling techniques discussed above. Read along and view the XML source code for each example.

Shuffle Question Elements

In the following example, the order of the brands shown at Q1 is maintained across the entire survey using several different shuffling methods.

<checkbox label="Q1" atleast="1" shuffle="rows">
  <title>
    Which brands are you aware of?
  </title>
  <comment>Please select all that apply</comment>
  <row label="r1">Brand 1</row>
  <row label="r2">Brand 2</row>
  <row label="r3">Brand 3</row>
  <row label="r4">Brand 4</row>
</checkbox>
<suspend/>


<checkbox label="Q2" onLoad="copy('Q1', rows=True)" shuffle="rows" shuffleBy="Q1" rowCond="Q1[row]">
  <title>
    Which brands have you purchased in the past 6 months?
  </title>
  <comment>Please select all that apply</comment>
</checkbox>
<suspend/>


<exec>Q3.rows.order = Q1.rows.order</exec>
<radio label="Q3" onLoad="copy('Q1', rows=True)" shuffle="rows" rowCond="Q1[row]">
  <title>
    Which brand is your favorite?
  </title>
  <comment>Please select one</comment>
</radio>
<suspend/>


<exec>Q4.cols.order = Q1.rows.order</exec>
<checkbox label="Q4" atleast="1" shuffle="rows,cols" colCond="col.label == 'c5' or Q1.rows[col.index]">
  <title>
    Please check which brand has these characteristics?
  </title>
  <comment>Please select all that apply</comment>
  <col label="c1">Brand 1</col>
  <col label="c2">Brand 2</col>
  <col label="c3">Brand 3</col>
  <col label="c4">Brand 4</col>
  <col label="c5" exclusive="1" randomize="0">None of these</col>
  <row label="r1">Awesome</row>
  <row label="r2">Cool</row>
  <row label="r3">Fast</row>
</checkbox>
<suspend/>


<exec>
Characteristics_Loop_expanded.order = Q4.rows.order
</exec>
<loop label="Characteristics_Loop" vars="characteristic" randomizeChildren="1">
    <block label="bCharacteristics">

<radio label="Q5_[loopvar: label]" colCond="Q4[col].[loopvar: label]" shuffle="cols" exec="Q5_[loopvar: label].cols.order = Q4.cols.order">
  <title>
    Which brand is the most [loopvar: characteristic]?
  </title>
  <comment>Please select one</comment>
  <col label="c1">Brand 1</col>
  <col label="c2">Brand 2</col>
  <col label="c3">Brand 3</col>
  <col label="c4">Brand 4</col>
</radio>
<suspend/>

    </block>
    <looprow label="r1"><loopvar name="characteristic">awesome</loopvar></looprow>
    <looprow label="r2"><loopvar name="characteristic">cool</loopvar></looprow>
    <looprow label="r3"><loopvar name="characteristic">fast</loopvar></looprow>
</loop>

In the example above, several techniques are used to create a consistent survey:

  • shuffle="rows,cols" to shuffle the question's elements
  • rowCond="..."/colCond="..." to conditionally show each row/col
  • <exec>...</exec> to manually set the shuffle order
  • onLoad="copy(...)" to copy question elements from one to another
  • randomize="0" to prevent an element from being shuffled
  • Loop_expanded.order to shuffle the loop's children elements consistently with the original shuffle at Q4

Shuffle Questions

Using the <block> element and the randomizeChildren="1" attribute, you can shuffle entire questions. In the example below, the sections pertaining to each brand are shuffled by the original question, Q1. Each section will be contained in another <block> element which should have randomize="1" specified. A virtual question is also included to track the order in which each section was shown.

<checkbox label="Q1" atleast="1" shuffle="rows">
  <title>
    Which brands have you heard of?
  </title>
  <comment>Please select all that apply</comment>
  <row label="r1">Brand 1</row>
  <row label="r2">Brand 2</row>
  <row label="r3">Brand 3</row>
  <row label="r4">Brand 4</row>
</checkbox>
<suspend/>


<exec>Brands_Section.order = Q1.rows.order</exec>
<block label="Brands_Section" randomizeChildren="1">

  <block label="Brand_1" randomize="1" cond="Q1.r1">
     <radio label="B1_1" type="rating" values="order">
       <title>
         On a scale from 1 - 5, how do you feel about Brand 1?
       </title>
       <comment>Please select one</comment>
       <col label="c1">1</col>
       <col label="c2">2</col>
       <col label="c3">3</col>
       <col label="c4">4</col>
       <col label="c5">5</col>
     </radio>
     <suspend/>
  </block>

  <block label="Brand_2" randomize="1" cond="Q1.r2">
     <radio label="B2_1" type="rating" values="order" onLoad="copy('B1_1', cols=True)">
       <title>
         On a scale from 1 - 5, how do you feel about Brand 2?
       </title>
       <comment>Please select one</comment>
     </radio>
     <suspend/>
  </block>

  <block label="Brand_3" randomize="1" cond="Q1.r3">
     <radio label="B3_1" type="rating" values="order" onLoad="copy('B1_1', cols=True)">
       <title>
         On a scale from 1 - 5, how do you feel about Brand 3?
       </title>
       <comment>Please select one</comment>
     </radio>
     <suspend/>
  </block>

  <block label="Brand_4" randomize="1" cond="Q1.r4">
     <radio label="B4_1" type="rating" values="order" onLoad="copy('B1_1', cols=True)">
       <title>
         On a scale from 1 - 5, how do you feel about Brand 4?
       </title>
       <comment>Please select one</comment>
     </radio>
     <suspend/>
  </block>

</block>

<number label="vBrand_Order" size="1">
  <virtual>assignRandomOrder('Brands_Section', 'children')</virtual>
  <title>
    Order of Brands Shown
  </title>
  <row label="Brand_1">Brand 1</row>
  <row label="Brand_2">Brand 2</row>
  <row label="Brand_3">Brand 3</row>
  <row label="Brand_4">Brand 4</row>
</number>

Extracted from the "Tracking Files" data download, the data shows that each brand section was, indeed, shuffled by Q1:

Q1_rows         Brands_Section_children
r4,r3,r2,r1     Brand_4,Brand_3,Brand_2,Brand_1
r1,r3,r4,r2     Brand_1,Brand_3,Brand_4,Brand_2
r2,r4,r1,r3     Brand_2,Brand_4,Brand_1,Brand_3
r2,r1,r4,r3     Brand_2,Brand_1,Brand_4,Brand_3
r1,r2,r4,r3     Brand_1,Brand_2,Brand_4,Brand_3
r2,r3,r1,r4     Brand_2,Brand_3,Brand_1,Brand_4
r3,r1,r2,r4     Brand_3,Brand_1,Brand_2,Brand_4
r3,r1,r4,r2     Brand_3,Brand_1,Brand_4,Brand_2
r2,r1,r3,r4     Brand_2,Brand_1,Brand_3,Brand_4
...
...

You can also see this information replicated in the vBrand_Order virtual question that was created:

vBrand_OrderBrand_1	vBrand_OrderBrand_2	vBrand_OrderBrand_3	vBrand_OrderBrand_4
4	                3	                2	                1
1	                4	                2	                3
3	                1	                4	                2
2	                1	                4	                3
1	                2	                4	                3
3	                1	                2	                4
2	                3	                1	                4
2	                4	                1	                3
2	                1	                3	                4
...

Recording Shuffle Order for Loops

Below is example of how to use assignRandomOrder() to obtain the order of looprows in a loop. The loop is labeled l1 and the looprows are labeled r1, r2, and r3. In the assignRandomOrder() function, you will reference the loop label followed by _expanded. The labels for the rows will be in the following format: [loop label]_[looprow label]_expanded.

<loop label="l1" randomizeChildren="1" vars="q1">
  <title>L1 Loop</title>
  <block label="b1" builder:title="default loop block">
    <text 
    label="q2_[loopvar: label]"
    optional="0"
    randomize="0"
    size="25">
      <title>What do you like about [loopvar: q1]?</title>
      <comment>be specific</comment>
    </text>
  </block>

  <looprow label="r1" cond="(q1.r1)">
    <loopvar name="q1">Brand 1</loopvar>
  </looprow>

  <looprow label="r2" cond="(q1.r2)">
    <loopvar name="q1">Brand 2</loopvar>
  </looprow>

  <looprow label="r3" cond="(q1.r3)">
    <loopvar name="q1">Brand 3</loopvar>
  </looprow>
</loop>

<number 
  label="l1_LOOP_ORDER"
  size="1">
  <title>l1 Loop Order</title>
  <virtual>
assignRandomOrder('l1_expanded', 'children')
  </virtual>

  <row label="l1_r1_expanded">Loop 1</row>
  <row label="l1_r2_expanded">Loop 2</row>
  <row label="l1_r3_expanded">Loop 3</row>
</number>

Note: In the example above, each brand-specific question is wrapped in a <block> with randomize="1" set. This is because, in a typical survey, there would be many brand-specific questions to ask. Since each block contains only one question, you could remove them and the shuffling would still be consistent. You would, however, need to update your rows at vBrand_Order to reflect the question labels instead of the block labels (e.g., "B4_1" instead of "Brand_4").

  • Was this article helpful?