Documentation

Numeric Grid Question

When and Why to Use

Use this to capture numeric input across a grid of rows and columns. Best for:

  • Time allocation or quantity distribution
  • Budget breakdowns
  • Structured numeric input across categories

Supports autosumming, recoding, and custom validation.

Chat Style
  • Each row is presented with numeric input fields for each column
  • Users enter numbers directly
Traditional Style
  • Full grid visible with scrollable columns if needed
  • Easier comparison across multiple categories
  • Autosums are enabled
Chat styleTraditional with imagesMobile optimized
Markdown 2B 2B 2BImagesText ImagesNumeric Grid Question Figure 01
Two-column traditionalTwo-column mobile optimized
Two-column numeric gridTwo-column numeric grid mobile
Configuration Options
OptionTypeRequiredDefaultDescription
questionstringyes-The prompt shown to the user
rowsList[str | MediaItem]yes-Rows to show in the grid
row_namestringyes-Reporting label for rows
columnsList[str]no-Column labels
column_namestringno-Reporting label for columns
imageMediaItemno-Top-level image
min_maxTuple[int, int]no(1, 10)Inclusive range of acceptable numeric values
randomizeboolnoFalseRandomize row order
randomize_columnsboolnoFalseRandomize column order
recodesDict[str, str]no-Optional recoding logic
defaultDict[str, int | Dict[str, int]] | List[Dict]norandomTest-data defaults keyed by row (or by row, then column, when columns are used), or a list of candidate dictionaries — each simulated respondent picks one at random
autosum_columnsboolnoFalseRequire responses to sum correctly by column
autosum_rowsboolnoFalseRequire responses to sum correctly by row
custom_validatorCallable[[Dict[str, int] | int], str | None]nostraight-line checkCalled with the parsed grid dictionary in the traditional experience, or with each parsed number in the chat experience (asked row by row); return an error message to reject
image_label_fieldstrno-Used to label media row items
show_image_labelboolnoTrueShow/hide labels for row images
image_sizeTuple[int, int]no(600, 600)Bounding box for images
number_secondsintno0Seconds to wait before allowing the respondent to continue
tagss.tag()no-Token substitution and reporting group
idstrno-Optional stable identifier for this question
Example Code

Basic usage:

s.grid_numeric_question( "How many hours do you spend per week on the following activities?", row_name="Activity", rows=["Work", "Sleep", "Exercise", "Socializing"], columns=["Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"] )

With recodes and autosum:

s.grid_numeric_question(
    "Distribute your budget across categories",
    row_name="Category",
    rows=["Food", "Housing", "Entertainment"],
    columns=["January", "February", "March"],
    recodes={
        "0-30%": "Low",
        "31-70%": "Medium",
        "71-100%": "High"
    },
    autosum_rows=True
)
Response shape by survey version

For version 4 surveys, a multi-column numeric grid returns a row-first DictResponse. The outer keys are row labels and each value is a dictionary keyed by column:

response = s.grid_numeric_question(
    "How many hours do you spend per day on each activity?",
    rows=["Work", "Sleep"],
    row_name="Activity",
    columns=["Monday", "Tuesday"],
    column_name="Day",
)

for activity, days in response.items():
    for day, value in days.items():
        s.store_value(
            "Stored numeric-grid value",
            value,
            tags=s.tag(Activity=activity, Day=day),
        )

The shape is:

{
    "Work": {"Monday": 8, "Tuesday": 8},
    "Sleep": {"Monday": 7, "Tuesday": 7},
}

In version 2 and version 3 surveys, the return shape is column-first, with columns outside and rows inside:

{
    "Monday": {"Work": 8, "Sleep": 7},
    "Tuesday": {"Work": 8, "Sleep": 7},
}

Iterate row then column in version 4, and column then row in versions 2 and 3. The default parameter is row-first — keyed by row and then column — in every supported version.

With custom validation:

s.grid_numeric_question(
    "How many units of each product did you sell?",
    row_name="Product",
    rows=["Item A", "Item B"],
    columns=["Online", "In-store"],
    custom_validator=lambda d: "Please don't enter the same number for every cell"
        if len(dict.fromkeys([v for row in d.values() for v in row.values()])) == 1
        else None
)
Notes
  • Returns a DictResponse containing the entered numbers; version 4 multi-column grids are row-first, while versions 2 and 3 are column-first
  • Use autosum_columns or autosum_rows to require entries that sum correctly by column or by row
  • Recodes are especially helpful for analysis of numeric ranges
  • A straight-line check is applied by default — pass your own custom_validator to replace it