Skip to main content

Decipher Support

All the topics, resources needed for Decipher.

FocusVision Knowledge Base

Adding a Typing Tool/Segmentation Algorithm to Your Survey

1:  Overview

The following article describes how to implement a Typing Tool/Segmentation algorithm into your your survey. This method is commonly used with Fisher's linear discriminant analysis and ran against a "Single Select Grid Question".  

2:  Preparing the Typing Tool File

The file must be a tab delimited file with segments as columns and coefficients as rows.  The constant should be the last row.  Name the file algorithm.dat and upload it to the “System File (root)” using the project’s File Manager.  An example file can be downloaded here for reference.

Note: The header row must be included!  Also ensure the last row doesn't have an extra line.

3:  Add Pre-Created Functions

The next step is to add the pre-created functions we've created to make this a bit easier.  Add a Structual > Exec element anywhere in your survey.  Enter the below in the text box and change the "When" setting to "init".  For the most part, this code never needs to change.  

def algorithmSetup(fname, fDelimiter="\t"):
        f = open("%s/%s" % (gv.survey.path, fname))
        algObj = [ line.strip("\r\n").split(fDelimiter) for line in f.readlines() ]

        algorithmObj = {}

        #Number of Segments
        algorithmObj['segments'] = len(algObj[0])

        #Create segment:[coefficient+constant]
        for s in range(algorithmObj['segments']):
            algorithmObj[s+1] = [float(row[s]) for row in algObj[1:]]

        return algorithmObj
    except IOError:
        algorithmObj = {}
    return algorithmObj

def algorithmCalculation(resp_answers, segment_coeff):
    return sum(i*j for i,j in zip(resp_answers, segment_coeff)) + segment_coeff[-1]

def algorithmRaw(answers, algorithmObj):
    computation = [ algorithmCalculation(answers, algorithmObj[c]) for c in range(1, algorithmObj['segments'] + 1) ]
    return computation

def algorithmCompute(answers, algorithmObj):
    computation = [ algorithmCalculation(answers, algorithmObj[c]) for c in range(1, algorithmObj['segments'] + 1) ]
    maxValue = max(computation)
    return computation.index(maxValue) + 1

myalg = algorithmSetup("algorithm.dat")


4:  Add Single Select Grid Question

Typing Tools are generally ran against a Single Select Grid Question.  In our example, our grid question has 12 rows and can accept values 1-5 for responses.  Program this as you would normally.  We will set the question label to  "QALG" for our example.  Now add a page break after this single select grid question.

5:  Create a Raw Score & Segment Assigned Question

We'll want to store the results of our calculation and segment assigned to a hidden question.  This will allow us to verify our results and even use the segment assigned in logic/quotas.  

Add a Standard > Text survey element and then add a Standard > Single Select survey element.  In both questions, specify the "where" setting from "More Options" and enter "execute" in the box.  In both questions, add the same number of rows as you have segments in your typing tool.  

In this example, we have 7 segments.  As displayed in the graphics below, we will label:

  • raw score text question "QALG_RAW"
  • segment assigned single select question "QALG_SEG"

Note, these 2 questions should go after the QALG question.  There must be a Page Break after QALG.

Raw Score Text Question


Segment Assigned Single Select Question


6:  Computing the Raw Scores & Segment Assigned

Typing tools are calculated using the Single Select Grid Question we programmed in step 4.  We take each of the 12 rows and their values (1-5) and multiply them by the coefficients then add the constant. The max value after all calculations are made for each segment determines which segment your respondent is assigned to.  

Let's add the code to do this.

Add a Structural > Exec element before the QALG_RAW/QALG_SEG question.  Enter the below into the text box.

#Respondent Answers Mapped
p.resp_answers = [, c2=2, c3=3, c4=4, c5=5) for row in QALG.rows ]
print "Respondent Answers: %s" % p.resp_answers

#Populate the Raw Calculations
for i,x in enumerate(algorithmRaw(p.resp_answers, myalg)):
    QALG_RAW.rows[i].val = str(x)

#Populate the Segment Assigned
QALG_SEG.val = algorithmCompute(p.resp_answers, myalg) - 1


Tip: If you have additional values or a different type of mapping, you can modify the p.resp_answers line.

Example 1:  If you had 8 options instead of the 5, you would modify the code to this:

p.resp_answers = [, c2=2, c3=3, c4=4, c5=5, c6=6, c7=7, c8=8) for row in QALG.rows ]

Example 2:  If you had -4, -2, 0, 2, 4 as your mapped values, you would modify the code to this:

p.resp_answers = [, c2=-2, c3=0, c4=2, c5=4) for row in QALG.rows ]

7:  Testing Your Survey

Test your survey as you normally would.  Once you get to the QALG_RAW/QALG_SEG question, you'll notice calculations were performed and a segment punched.  This question is hidden to respondents and is only shown for logged in users when "Show Survey with Tools" is selected for the Survey Test Environment. This can be used to verify that the typing tool is working correctly.