Welcome to the LimeSurvey Community Forum

Ask the community, share ideas, and connect with other LimeSurvey users!

Distribute participant randomly and automatically in groups taking account age

  • Cjonath
  • Cjonath's Avatar Topic Author
  • Offline
  • New Member
  • New Member
More
4 years 3 months ago #212625 by Cjonath
Hello again

In my survey, I will randomly separate participants into four groups, but I would like these four groups to have similar characteristics in age and gender.

Age and gender will be asking each one in a specific question. The question of age has 3 answer options (the first is still 39 years old, the second is 40 to 59 years old and the third is over 59 years old). The gender question has 3 answer options (male; female; other).

For group randomization, I am using the function in a question that is not being displayed to the participant:

{if ((Q1> 25 AND Q2> 84) OR Q3 == "Y" OR Q4> = 2.61, "G1", if (CODGRUPO> = 1, CODGRUPO, rand (1,4)))}}

Q1, Q2, Q3 AND Q4 ARE NOT ABOUT GENDER OR AGE.

With that question, my research automatically randomized participants into four groups, but it does not take gender or age into account.

Can someone help me?

From now on, thank you very much!
The topic has been locked.
  • holch
  • holch's Avatar
  • Offline
  • LimeSurvey Community Team
  • LimeSurvey Community Team
More
4 years 3 months ago #212636 by holch
I would say, what you are trying is NOT possible, at least not with a huge amount of external programming.

First of all, your random number will never guarantee perfectly equal groups just based on that number alone. The bigger your sample size, the higher the chances that you get close to 25% of your respondents in each group, but not more.

Now you want also an even distribution based on not just 1 characteristic, but 2. I mean, this is not impossible, I guess, bug it will require significant work I would say.

So basically what you want is a "least filled bucked" I guess. In reality you probably need 4x 3x 3x buckets or something to achieve this.

Looks complicated to me. Maybe someone else (Joffm, I look at you... ;-) ), will find a genius solution.

Help us to help you!
  • Provide your LS version and where it is installed (own server, uni/employer, SaaS hosting, etc.).
  • Always provide a LSS file (not LSQ or LSG).
Note: I answer at this forum in my spare time, I'm not a LimeSurvey GmbH employee.
The topic has been locked.
  • Cjonath
  • Cjonath's Avatar Topic Author
  • Offline
  • New Member
  • New Member
More
4 years 3 months ago #212664 by Cjonath
Thank you very much for the answer Holch.

I thought it wouldn't be simple: /

Well, I can only hope that someone still has an idea.
The topic has been locked.
More
4 years 3 months ago #212668 by jelo
You want to ensure that age and gender plays no role in your four different groups, right?

Age (L)ow (M)iddle (H)igh / Gender M F O
Results into nine groups LM,LF,LO,MM,MF,MO,HM,HF,HO

Every of these nine group need to be exposed to four stimuli groups (and you want them to split even 25% 25% 25% 25%).

There are 36 groups (9 x 4). So you would have 36 counter, which you would need to be check manually and adapt manually to ensure 25,25,25,25% in each agegroup.
The workaround uses in other task, helps to close a group for a certain agegendergroup over time. Depending on the amount of respondents you expect, you can let the system run for a certain time and then pausing stimuli groups for certain agegender-groups. That might work, if the flow of respondents is not very fast and you have a certain amount of respondents. I might have not fully grasped your task.

The meaning of the word "stable" for users
www.limesurvey.org/forum/development/117...ord-stable-for-users
The topic has been locked.
  • Joffm
  • Joffm's Avatar
  • Offline
  • LimeSurvey Community Team
  • LimeSurvey Community Team
More
4 years 3 months ago - 4 years 3 months ago #212671 by Joffm
As Jelo showed there are 36 groups.
I should use the plugin "getStatInSurvey" to fetch the actual numbers of each group.
Now, if we code like this
1: young
2: mid
3: old
and
1: male
2: female
3: other

we get this
 

Let's say:
we have age group=1 and gender=3.
So we only have to find the minimum of the cells 3, 12, 21, 30 to find the least filled group of the four.
This is easy to calculate by 9 * (group-1) + 3 * (age-1) + gender

Just to say.
I am creating an example.

Joffm

Volunteers are not paid.
Not because they are worthless, but because they are priceless
Last edit: 4 years 3 months ago by Joffm.
The following user(s) said Thank You: holch
The topic has been locked.
  • Joffm
  • Joffm's Avatar
  • Offline
  • LimeSurvey Community Team
  • LimeSurvey Community Team
More
4 years 3 months ago #212691 by Joffm
Here a sample survey
 

File Attachment:

File Name: limesurvey...4464.lss
File Size:48 KB


As I said I use the plugin "getStatsInSurvey"

To count the 36 possible groups I create a question of type "list(radio)" ("QGA"), which is hidden.
Next I created a question of type array(text) ("QGB") with 9 rows (all combinations of age and gender) and 4 columns.
Here the plugin is called.
It catptures the values of all 36 outcomes and saves it into the cells of the array.
Code:
<script type="text/javascript" charset="utf-8">
$(document).on('ready pjax:scriptcomplete',function(){
  var total1=Math.floor({' [QGA.nb.1]'});
  var total2=Math.floor({' [QGA.nb.2]'});
  var total3=Math.floor({' [QGA.nb.3]'});
  var total4=Math.floor({' [QGA.nb.4]'});
  var total5=Math.floor({' [QGA.nb.5]'});
  var total6=Math.floor({' [QGA.nb.6]'});
  var total7=Math.floor({' [QGA.nb.7]'});
  var total8=Math.floor({' [QGA.nb.8]'});
  var total9=Math.floor({' [QGA.nb.9]'});
  var total10=Math.floor({' [QGA.nb.10]'});
  var total11=Math.floor({' [QGA.nb.11]'});
  var total12=Math.floor({' [QGA.nb.12]'});
  var total13=Math.floor({' [QGA.nb.13]'});
  var total14=Math.floor({' [QGA.nb.14]'});
  var total15=Math.floor({' [QGA.nb.15]'});
  var total16=Math.floor({' [QGA.nb.16]'});
  var total17=Math.floor({' [QGA.nb.17]'});
  var total18=Math.floor({' [QGA.nb.18]'});
  var total19=Math.floor({' [QGA.nb.19]'});
  var total20=Math.floor({' [QGA.nb.20]'});
  var total21=Math.floor({' [QGA.nb.21]'});
  var total22=Math.floor({' [QGA.nb.22]'});
  var total23=Math.floor({' [QGA.nb.23]'});
  var total24=Math.floor({' [QGA.nb.24]'});
  var total25=Math.floor({' [QGA.nb.25]'});
  var total26=Math.floor({' [QGA.nb.26]'});
  var total27=Math.floor({' [QGA.nb.27]'});
  var total28=Math.floor({' [QGA.nb.28]'});
  var total29=Math.floor({' [QGA.nb.29]'});
  var total30=Math.floor({' [QGA.nb.30]'});
  var total31=Math.floor({' [QGA.nb.31]'});
  var total32=Math.floor({' [QGA.nb.32]'});
  var total33=Math.floor({' [QGA.nb.33]'});
  var total34=Math.floor({' [QGA.nb.34]'});
  var total35=Math.floor({' [QGA.nb.35]'});
  var total36=Math.floor({' [QGA.nb.36]'});
  $('#answer{SGQ}Y001_X001').val(total1);
  $('#answer{SGQ}Y002_X001').val(total2);
  $('#answer{SGQ}Y003_X001').val(total3);
  $('#answer{SGQ}Y004_X001').val(total4);
  $('#answer{SGQ}Y005_X001').val(total5);
  $('#answer{SGQ}Y006_X001').val(total6);
  $('#answer{SGQ}Y007_X001').val(total7);
  $('#answer{SGQ}Y008_X001').val(total8);
  $('#answer{SGQ}Y009_X001').val(total9);
  $('#answer{SGQ}Y001_X002').val(total10);
  $('#answer{SGQ}Y002_X002').val(total11);
  $('#answer{SGQ}Y003_X002').val(total12);
  $('#answer{SGQ}Y004_X002').val(total13);
  $('#answer{SGQ}Y005_X002').val(total14);
  $('#answer{SGQ}Y006_X002').val(total15);
  $('#answer{SGQ}Y007_X002').val(total16);
  $('#answer{SGQ}Y008_X002').val(total17);
  $('#answer{SGQ}Y009_X002').val(total18);
  $('#answer{SGQ}Y001_X003').val(total19);
  $('#answer{SGQ}Y002_X003').val(total20);
  $('#answer{SGQ}Y003_X003').val(total21);
  $('#answer{SGQ}Y004_X003').val(total22);
  $('#answer{SGQ}Y005_X003').val(total23);
  $('#answer{SGQ}Y006_X003').val(total24);
  $('#answer{SGQ}Y007_X003').val(total25);
  $('#answer{SGQ}Y008_X003').val(total26);
  $('#answer{SGQ}Y009_X003').val(total27);
  $('#answer{SGQ}Y001_X004').val(total28);
  $('#answer{SGQ}Y002_X004').val(total29);
  $('#answer{SGQ}Y003_X004').val(total30);
  $('#answer{SGQ}Y004_X004').val(total31);
  $('#answer{SGQ}Y005_X004').val(total32);
  $('#answer{SGQ}Y006_X004').val(total33);
  $('#answer{SGQ}Y007_X004').val(total34);
  $('#answer{SGQ}Y008_X004').val(total35);
  $('#answer{SGQ}Y009_X004').val(total36);
//  $('#question{QID}').hide();
});
</script>

There will be a shorter solution, but I am not able to do it.

Now we see this overview (of course also hidden by uncommenting the line "//  $('#question{QID}').hide();")
 

Let's concentrate on the red marked rows.
You see
1. the next selected group of "mid-female" should be Group 1
2. the next selected group of "mid-male" should be one of Group 1, 2 or 4.

Okay, next.
By the values of age and gender you can calculate the row
{(3*(age-1)+gender)}
This is done in the first equation "eqGroup"

Now you find the minimum value in this row by (do not copy this without removing the line feeds)
{
if(eqGroup==1,min(that.QGB.sq_Y001.NAOK),
  if(eqGroup==2,min(that.QGB.sq_Y002.NAOK),
    if(eqGroup==3,min(that.QGB.sq_Y003.NAOK),
      if(eqGroup==4,min(that.QGB.sq_Y004.NAOK),
        if(eqGroup==5,min(that.QGB.sq_Y005.NAOK),
          if(eqGroup==6,min(that.QGB.sq_Y006.NAOK),
            if(eqGroup==7,min(that.QGB.sq_Y007.NAOK),
              if(eqGroup==8,min(that.QGB.sq_Y008.NAOK),
                min(that.QGB.sq_Y009.NAOK)
              )
            )
          )
        )
      )
    )
  )
)
}


This is done in equation "eqMinVal".

Now you know the minimum value, but still you don't know which group has this value.
In the next equation
{
if(eqGroup==1,join(if(QGB_Y001_X001==eqMinVal,"1",""),if(QGB_Y001_X002==eqMinVal,"2",""),if(QGB_Y001_X003==eqMinVal,"3",""),if(QGB_Y001_X004==eqMinVal,"4","")), 
  if(eqGroup==2,join(if(QGB_Y002_X001==eqMinVal,"1",""),if(QGB_Y002_X002==eqMinVal,"2",""),if(QGB_Y002_X003==eqMinVal,"3",""),if(QGB_Y002_X004==eqMinVal,"4","")), 
    if(eqGroup==3,join(if(QGB_Y003_X001==eqMinVal,"1",""),if(QGB_Y003_X002==eqMinVal,"2",""),if(QGB_Y003_X003==eqMinVal,"3",""),if(QGB_Y003_X004==eqMinVal,"4","")), 
      if(eqGroup==4,join(if(QGB_Y004_X001==eqMinVal,"1",""),if(QGB_Y004_X002==eqMinVal,"2",""),if(QGB_Y004_X003==eqMinVal,"3",""),if(QGB_Y004_X004==eqMinVal,"4","")), 
        if(eqGroup==5,join(if(QGB_Y005_X001==eqMinVal,"1",""),if(QGB_Y005_X002==eqMinVal,"2",""),if(QGB_Y005_X003==eqMinVal,"3",""),if(QGB_Y005_X004==eqMinVal,"4","")), 
          if(eqGroup==6,join(if(QGB_Y006_X001==eqMinVal,"1",""),if(QGB_Y006_X002==eqMinVal,"2",""),if(QGB_Y006_X003==eqMinVal,"3",""),if(QGB_Y006_X004==eqMinVal,"4","")), 
            if(eqGroup==7,join(if(QGB_Y007_X001==eqMinVal,"1",""),if(QGB_Y007_X002==eqMinVal,"2",""),if(QGB_Y007_X003==eqMinVal,"3",""),if(QGB_Y007_X004==eqMinVal,"4","")), 
              if(eqGroup==8,join(if(QGB_Y008_X001==eqMinVal,"1",""),if(QGB_Y008_X002==eqMinVal,"2",""),if(QGB_Y008_X003==eqMinVal,"3",""),if(QGB_Y008_X004==eqMinVal,"4","")), 
                join(if(QGB_Y009_X001==eqMinVal,"1",""),if(QGB_Y009_X002==eqMinVal,"2",""),if(QGB_Y009_X003==eqMinVal,"3",""),if(QGB_Y009_X004==eqMinVal,"4",""))
              )
            )
          )
        )
      )
    )
  )
)
}

you join all group numbers that contain this minimum value.
Done in equation "eqMinGroup"

Now you generate a random number from 1 to the length of the joined string.
{if(is_empty(eqRandGroup),rand(1,strlen(eqMinGroup))-1,eqRandGroup)}
Done in equation "eqRandGroup"

The last step is to set this found group number in the list(radio)
{QGA=9*(sum(eqEndGroup,-1))+eqGroup}


Let's see it live.
I selected "mid-male" and the row is calculated as 4th.
 

Here the minimum is "0" in columns 1, 2 and 4.

Here you see the result of the equations. In a real survey these are hidden, of course.
 

And here just an info page that shows the result.
 

BUT:
This only works really fine, if there are not too many participants answering the survey at the same time.
Only completed surveys are taken in account.
So imagine:
At the start all cells are empty.
If 50 young males start the survey at the same time they are distributed at random to the four groups.
This way there is no advantage to a pure random distribution.
To avoid this you should send out the invitations in batches spread over some time.

Joffm

Volunteers are not paid.
Not because they are worthless, but because they are priceless
The following user(s) said Thank You: holch
The topic has been locked.
  • Joffm
  • Joffm's Avatar
  • Offline
  • LimeSurvey Community Team
  • LimeSurvey Community Team
More
4 years 3 months ago #212692 by Joffm
There is one step missing.

After 
Done in equation "eqRandGroup"

Now we get the final group number from the joined string by
{substr(eqMinGroup,eqRandGroup,1)}
Remember: "substr" starts at "0".
Done in equation "eqEndGroup"

Joffm

Volunteers are not paid.
Not because they are worthless, but because they are priceless
The topic has been locked.
  • Cjonath
  • Cjonath's Avatar Topic Author
  • Offline
  • New Member
  • New Member
More
4 years 3 months ago #212724 by Cjonath
Thank you very much Jelo and especially to you Joffm

I am very happy with the help I have received here!

I’m going to work with it this week and I'll share the result with you.

Thank you again.
The topic has been locked.
  • Cjonath
  • Cjonath's Avatar Topic Author
  • Offline
  • New Member
  • New Member
More
4 years 3 months ago #213031 by Cjonath
Thanks again

But I had a new problem. I use the Limesurvey that is available from my University and the solution did not work, because they does not allow the installation of the plugin.

My question is: Is there any way to use this solution without the getStatsInSurvey plugin?

I used this solution on my private profile (outside the university) and it worked, even though I didn't install the plugin either.

Thanks in advance
The topic has been locked.
  • Joffm
  • Joffm's Avatar
  • Offline
  • LimeSurvey Community Team
  • LimeSurvey Community Team
More
4 years 3 months ago #213034 by Joffm
Well then you have to use a simple ramdom number to distribute your participants.
And you have to watch the distribution of age and gender.
So you can change the relevance equations to your needs.
Equations you can always change; even in an activated survey.

Example:
After 50% of the expected responses you see that in group 4  there are not enough young males, but in group 3 there are enough.
So you can create an equation ("finalgroup")  like
{if(age==1 and gender==1 and randomnumber==3, 4,randomnumber)}
Meaning: if "young" and "male" and "randomnumber==3" THEN the finalgroup is set to 4 ELSE the finalgroup is like the randomnumber.

Of course you may nest the if statement.

And you use "finalgroup" for your relevance equations.

Joffm

Volunteers are not paid.
Not because they are worthless, but because they are priceless
The topic has been locked.
Moderators: tpartnerholch

Lime-years ahead

Online-surveys for every purse and purpose