Choosing multiple respondents randomly (without replacement) from a list

Dear Survey Solutions Support,

I want to enable a roster of questions only for a randomly selected group of respondents (without replacement).

Specifically, I first make a list of respondents (called staff) that is capped at 40 rows.
If in an interview there are more than 10 respondents, I want to randomly select 10 respondents from the list. Otherwise, all listed respondents will continue with the roster questions.

I have tried a fairly labour-intensive solution (described below), but what would be the most efficient way of doing this?

  1. I have created a 10x30 array of random integers in STATA, which gives me the @roworder for all possible sizes of the list (11,12,…,40) that would require randomly drawing 10 respondents. The array is stored outside of the questionnaire.

  2. I have created 30 subsections, each subsection has a different enabling condition.
    The first subsection has enabling condition:
    staff.Count()==11
    The second subsection has enabling condition:
    staff.Count()==12

    staff.Count()==40

  3. Each of the 30 subsection contains the same roster of questions, but each of the rosters has different enabling condition specifying the @roworder of staff that corresponds to a randomly drawn number in a column of the 10x30 array. For example, the first roster has the enabling condition:
    @rowcode==7 || @rowcode==4 || @rowcode==11 || @rowcode==6 || @rowcode==5 || @rowcode==10 || @rowcode==9|| @rowcode==1|| @rowcode==2|| @rowcode==8 //Where the @roworder==3 has been left out.

Moreover, I have noticed that the way I have gone about this does not work if I delete an element from the list, because the @roworder does not update. I have consulted previous threads and the randomization.pdf, but did not find a better solution.

Many thanks in advance.
Best wishes,
G

Hello Giulio Schinaia,

as far as I can see, you can have one random sequence of numbers (1…40) in the random order, e.g.:
23,19,3,13,28,33,7,32,38,4,20,2,10,12,18,29,25,5,9,16,15,26,22,36,34,24,14,31,11,27,1,30,6,40,39,8,37,17,21,35
which you can subsequently filter to contain only valid indices (given the actual number of staff):
new[] {23,19,3,13,28,33,7,32,38,4,20,2,10,12,18,29,25,5,9,16,15,26,22,36,34,24,14,31,11,27,1,30,6,40,39,8,37,17,21,35}.Select(x=>x<staff.Count())
resulting in a random sequence of indices all of which are valid.

Take the first 10 or all, whichever is smaller. Literally use C#'s Take() method
https://msdn.microsoft.com/en-us/library/bb503062(v=vs.110).aspx

Finally, verify if the resulting sequence Contains() the @rowcode of a particular staff.

This will always select the same staff numbers for a given size of the roster, If this is not random enough, you can toggle between 2 or more of such random sequences, or as in the Kish method assign different sequences depending on the roster size as well.

Best, Sergiy Radyakin

Dear Giulio Schinaia,

  1. Yes if there is only a single random sequence and it is as shown, then from 11 respondents #8 will be skipped;
  2. You can place the whole sequence directly into the enabling condition (expression) field for the roster:

(new[] {23,19,3,13,28,33,7,32,38,4,20,2,10,12,18,29,25,5,9,16,15,26,22,36,34,24,14,31,11,27,1,30,6,40,39,8,37,17,21,35}.Where(x=>x<staff.Count())).Take(Math.Min(10,staff.Count())).ToArray().Contains((int)@rowcode)

Of course for convenience and readability you can place the sequence into a macro.

Best, Sergiy

Thanks Sergiy,

I understand the idea of getting a single random sequence and then selecting the same order for a given size of the roster.

  1. In your sequence example, if I had 11 respondents, I’d always not select @rowcode==8, is that right?

2)Unfortunately, I am unsure as to how this is implemented. Where do you store/save the sequence:
new[] {23,19,3,13,28,33,7,32,38,4,20,2,10,12,18,29,25,5,9,16,15,26,22,36,34,24,14,31,11,27,1,30,6,40,39,8,37,17,21,35}.Select(x=>x<staff.Count())
?

I can’t really be a variable, as I don’t see how you’d store an array in a variable. Or is your reply all part of the same code in an enabling condition? If so, I still don’t really see how I’d select the required @rowcode from the list created during the interview.

Your support is much appreciated, I don’t have any prior experience with C#, so a lot is still new to me.

Much obliged,
Giulio

(In my previous question whenever I wrote @roworder, I meant @rowcode…)

Thanks a lot Sergiy,

The issue has been resolved!

I couldn’t fully read your last reply, until I viewed the Source Page, so ended up getting stuck with the data type that went into the condition. Then I saw you had included ToArray(). I have tweaked the code in three ways:

1)As suggested, I created a macro for the sequence $randomsq defined as {23,19,3,13,28,33,7,32,38,4,20,2,10,12,18,29,25,5,9,16,15,26,22,36,34,24,14,31,11,27,1,30,6,40,39,8,37,17,21,35}

  1. I have made the enabling conditional based on a conditional statement for the list size. To get the following:

staff.Count()>10?

(new[] $randomsq.Where(x=>x<staff.Count())).Take(10).ToArray().Contains((int)@rowindex)

: true

  1. Instead of using @rowcode, I am using @rowindex. This seems to allow me to delete and add rows from my original list during the interview, without reducing the number of elements selected from the enabling condition we discussed.

Best wishes,
Giulio

Dear Giulio,

thank you for confirming your issue is resolved now. Please, do not hesitate to submit questions to support again in the future.

Best, Sergiy