Using Advanced Python Features
ython’s standard library is packed with powerful modules that, when combined with MX8’s survey
API, can deliver advanced logic, smarter routing, and richer data handling — all within the sandbox’s safe execution limits. The allowed imports in the MX8 sandbox are:
collections – High-performance container datatypes like
Counter
anddefaultdict
for counting, grouping, and organizing data.datetime – Date and time handling, including comparisons, formatting, and time-zone safe calculations.
itertools – Tools for building iterators, cycles, combinations, permutations, and slices for controlled iteration.
math – Mathematical functions for advanced calculations (e.g., logarithms, square roots, trigonometry).
re – Regular expressions for pattern matching, searching, and text manipulation.
statistics – Functions for averages, medians, variance, and other statistical calculations.
string – String manipulation helpers and constants like punctuation and character sets.
time – Time-related functions like measuring elapsed time or adding pauses.
json – Encoding and decoding JSON strings for configuration-driven surveys.
This article provides examples of some of the stronger use cases for these modules to help you create more dynamic, responsive surveys.
Patterns with itertools
Balanced exposure with cycle
Rotate sequentially through creatives so exposure stays even.
from survey import Survey
import itertools
s = Survey(**globals())
creatives = s.media
rotator = itertools.cycle(creatives)
for _ in range(3):
s.rating_question(
"Rate this creative:",
image=next(rotator),
number_of_points=5
)
Pairwise comparisons with combinations
Efficiently create unique A vs. B questions.
from survey import Survey
import itertools, random
s = Survey(**globals())
brands = ["Nike", "Adidas", "Puma", "Reebok"]
pairs = list(itertools.combinations(brands, 2))
for b1, b2 in random.sample(pairs, k=3):
s.select_question("Which do you prefer?", options=[b1, b2])
Batched blocks with islice
Show only the next N assets from a larger list.
from survey import Survey
from itertools import islice
s = Survey(**globals())
subset = list(islice(s.media, 5))
for m in subset:
s.select_question("First look: thumbs up?", options=["Yes","No"], image=m)
Patterns with math
Log scaling for skewed spend
Compress extreme numeric values before routing.
from survey import Survey
import math
s = Survey(**globals())
spend = s.numeric_question("Monthly snack spend?", min_max=(0, 10000))
log_spend = math.log(spend + 1)
if log_spend > 6:
s.text_question("What drives your high spend?")
Euclidean distance for profile fit
Score how close ratings are to a target profile.
from survey import Survey
import math
s = Survey(**globals())
target = (5, 4, 4)
resp = (
s.rating_question("Quality?", number_of_points=5),
s.rating_question("Value?", number_of_points=5),
s.rating_question("Design?", number_of_points=5),
)
dist = math.sqrt(sum((r - t)**2 for r, t in zip(resp, target)))
if dist <= 2:
s.set_topics("on-target")
Nonlinear weighting with sqrt
Downweight extremes when aggregating signals.
from survey import Survey
import statistics, math
s = Survey(**globals())
ratings = [
s.rating_question("Message clarity", number_of_points=5),
s.rating_question("Believability", number_of_points=5),
s.rating_question("Relevance", number_of_points=5),
]
mean_score = statistics.mean(ratings)
std_like = math.sqrt(sum((x - mean_score)**2 for x in ratings) / len(ratings))
if std_like > 1.5:
s.text_question("Why were your ratings so varied?")
Patterns with statistics
Mean + dispersion check (consistency)
Follow up when responses are inconsistent.
from survey import Survey
import statistics, math
s = Survey(**globals())
ratings = [
s.rating_question("Message clarity", number_of_points=5),
s.rating_question("Believability", number_of_points=5),
s.rating_question("Relevance", number_of_points=5),
]
mean_score = statistics.mean(ratings)
std_like = math.sqrt(sum((x - mean_score)**2 for x in ratings) / len(ratings))
if std_like > 1.5:
s.text_question("Why were your ratings so varied?")
Top‑2‑box share with fmean
from survey import Survey
import statistics
s = Survey(**globals())
scores = [s.rating_question(f"Rate ad {i+1}", number_of_points=5) for i in range(6)]
Top2 = statistics.fmean(1 if x >= 4 else 0 for x in scores)
if Top2 < 0.4:
s.text_question("What held these ads back?")
else:
s.text_question("What made these ads work for you?")
Trimmed sentiment index
from survey import Survey
import statistics
s = Survey(**globals())
vals = [s.rating_question(q, number_of_points=5) for q in [
"Trust", "Uniqueness", "Appeal", "Purchase intent"
]]
avg = statistics.mean(vals)
med = statistics.median(vals)
if abs(avg - med) >= 1:
s.text_question("Some answers were polarized. What caused mixed feelings?")
Combining itertools
+ statistics
Ensure fair rotation and track live average.
from survey import Survey
import itertools, statistics
s = Survey(**globals())
rot = itertools.cycle(s.media)
collected = []
for _ in range(4):
r = s.rating_question("Overall impression", number_of_points=5, image=next(rot))
collected.append(r)
live_avg = statistics.mean(collected)
if live_avg < 3:
s.text_question("What would improve these creatives?")