Have an idea?

Visit Sawtooth Software Feedback to share your ideas on how we can improve our products.

Calculating Segment Scores and Assigning Segments on the Fly

I have a segmentation algorithm to classify respondents into 5 segments. This is based on their answers to a set of questions asked in a grid question. We need to identify the segments on the fly to track quotas. I need to create the Perl or javascript code that can get the job done without halting the survey while doing the calculations.

For the sake of simplification, let's say S1 is the segmentation grid question. There are 5 items in S1, so they would be S1_r1 to S1_r5. Each can take a value from 1 to 5 (grid scale). For the segmentation algorithm, we need to calculate each segment score using formulas like these below (multiplying the answer value by a numeric coefficient and adding them across the question items) and save the scores in the dataset as independent variables:
Seg1= (S1_r1*0.11)+ (S1_r2*0.12) +(S1_r3*0.13)+ (S1_r4*0.14)+ (S1_r5*0.15)
Seg2= (S1_r1*0.21)+ (S1_r2*0.22) +(S1_r3*0.23)+ (S1_r4*0.24)+ (S1_r5*0.25)
Seg3= (S1_r1*0.31)+ (S1_r2*0.32) +(S1_r3*0.33)+ (S1_r4*0.34)+ (S1_r5*0.35)
Seg4= (S1_r1*0.41)+ (S1_r2*0.42) +(S1_r3*0.43)+ (S1_r4*0.44)+ (S1_r5*0.45)
Seg5= (S1_r1*0.51)+ (S1_r2*0.52) +(S1_r3*0.53)+ (S1_r4*0.45)+ (S1_r5*0.55
Then we need to compare the scores from Seg1, Seg2, Seg3, Se4, Seg5 and    save a value from 1 to 5 in a flag variable, we call Segment for each respondents. So if Seg1 has the highest score value of all, then the assigned value would be 1 in the Segment variable. If Seg2 has highest score, then the assigned value would be 2, and so on.
What would be the code to set something like this in an efficient way? The actual segmentation question has 22 items, so I'm worried this will slow down or crash the survey while trying to assign the segment values)
asked Oct 30, 2021 by rinsights Bronze (890 points)

1 Answer

0 votes
I started by creating pass-in fields "Seg1," "Seg2," "Seg3," ... as well as "BestSeg."  Then I used this script to set the values:

[% Begin Unverified Perl
my $row1 = GETVALUE('S1_r1');
my $row2 = GETVALUE('S1_r2');
my $row3 = GETVALUE('S1_r3');

my $bestSeg = 0;
my $bestScore = 0;

my $seg1 = $row1 * .11 + $row2 * .12 + $row3 * .13;
SETVALUE('Seg1', $seg1);
if ($seg1 > $bestScore) {
    $bestSeg = 1;
    $bestScore = $seg1;
}

my $seg2 = $row1 * .21 + $row2 * .22 + $row3 * .23;
SETVALUE('Seg2', $seg2);
if ($seg2 > $bestScore) {
    $bestSeg = 2;
    $bestScore = $seg2;
}

my $seg3 = $row1 * .31 + $row2 * .32 + $row3 * .33;
SETVALUE('Seg3', $seg3);
if ($seg3 > $bestScore) {
    $bestSeg = 3;
    $bestScore = $seg3;
}

SETVALUE('BestSeg', $bestSeg);
End Unverified %]


My code is set up for three rows, but it should be fairly simple to expand it to satisfy your number of segments.

Your calculations don't sound like they're going to take a lot of time, but you can test the performance for yourself.
answered Nov 1, 2021 by Zachary Platinum Sawtooth Software, Inc. (201,875 points)
Thank you, Zach. Where is the code where you calculate the value for the $bestScore? I don't see how you compare the segment scores against each other only that you compare the individual seg scores to the $bestScore.
It's the same thing.  I initialize $bestScore to zero, a value that will be lower than any of the actual segmented scores.  Then for each segment, I compare its segment score to $bestScore and update $bestSeg and $bestScore if I found a new highest value.  After doing this on every segment, $bestScore will have the highest score of them all and $bestSeg will know which segment produced it.
Thank you, Zach. Is there a way to add labels to the values stored in Bestseg? For example, if the value is 1 then we want to call it "Optimist," if the value is 2 we want to call it "Naysayer" and so on.
It would be helpful to have a code to add labels to values from hidden variables so they show up when we run tables in the admin module and to get them as SPSS labels. Is this possible?
If the BestSeg variable is text type, we can just save whatever text you want to the field by changing lines 12, 19, 26, etc. to the text for that segment.

$bestSeg = 'Optimist';
I want to keep the numeric values for each segment and have the labels associated with a numeric value that is stored. How would this do that?
I'd just add a "$bestSegLabel" line of code after each "$bestSeg" line with the labels and the call SetValue twice to save the label to a second field.
Like this? Would the label be saved as separate variable?
[% Begin Unverified Perl
my $row1 = GETVALUE('S1_r1');
my $row2 = GETVALUE('S1_r2');
my $row3 = GETVALUE('S1_r3');
 
my $bestSeg = 0;
my $bestScore = 0;
 
my $seg1 = $row1 * .11 + $row2 * .12 + $row3 * .13;
SETVALUE('Seg1', $seg1);
if ($seg1 > $bestScore) {
    $bestSeg = 1;
    $bestScore = $seg1;
   $bestSegLabel = 'Label1';
}
 
my $seg2 = $row1 * .21 + $row2 * .22 + $row3 * .23;
SETVALUE('Seg2', $seg2);
if ($seg2 > $bestScore) {
    $bestSeg = 2;
    $bestScore = $seg2;
    $bestSegLabel = 'Label2';
}
 
my $seg3 = $row1 * .31 + $row2 * .32 + $row3 * .33;
SETVALUE('Seg3', $seg3);
if ($seg3 > $bestScore) {
    $bestSeg = 3;
    $bestScore = $seg3;
    $bestSegLabel = 'Label3';
}
 
SETVALUE('BestSeg', $bestSeg);
SETVALUE('BestSeg', $bestSegLabel);
End Unverified %]
Yes.  As-is, your code will save the numeric value to BestSeg, then immediately overwrite it by saving the label to BestSeg.
...