Documentation

Using Advanced Python Features

Python's standard library is packed with powerful modules that, when combined with MX8 Labs' survey API, can deliver advanced logic, smarter routing, and richer data handling, all within the sandbox's safe execution limits. The sandbox allows a curated set of standard-library modules — collections, datetime, itertools, json, math, random, re, statistics, string, and time — and no third-party packages such as pandas. The survey code editor flags any other import as it's typed. The allowed modules include:

  • collections - High-performance container datatypes like Counter and defaultdict 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.

For randomization, prefer the built-in helpers of the survey API over the standard library random module: s.randomize(items) shuffles a list (keeping any nested groups together, with flatten=True to flatten them afterward), and s.random() returns a float between 0 and 1 that is stable for the same respondent.

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. (The sandbox does not allow the next() builtin, so index into the list instead of using itertools.cycle directly.)

from survey import Survey

s = Survey(**globals())

creatives = s.media

for i in range(3):
    s.rating_question(
        "Rate this creative:",
        image=creatives[i % len(creatives)],
        number_of_points=5
    )
Pairwise comparisons with combinations

Efficiently create unique A vs. B questions.

from survey import Survey
import itertools

s = Survey(**globals())

brands = ["Nike", "Adidas", "Puma", "Reebok"]
pairs = list(itertools.combinations(brands, 2))

for b1, b2 in s.randomize(pairs)[:3]:
    s.select_question(
        "Which do you prefer?",
        options=[b1, b2],
        tags=s.tag(pair=f"{b1} vs {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.store_value("fit", "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?")
Fair rotation + live average with statistics

Ensure fair rotation and track live average.

from survey import Survey
import statistics

s = Survey(**globals())

creatives = s.media
collected = []
for i in range(4):
    r = s.rating_question(
        "Overall impression",
        number_of_points=5,
        image=creatives[i % len(creatives)]
    )
    collected.append(r)

live_avg = statistics.mean(collected)
if live_avg < 3:
    s.text_question("What would improve these creatives?")