Expressions

An expression is a small calculation, such as doubling a score or checking whether it is above a cutoff. You write it in Python; GenomeSpy works out the answer in the browser.

Calculate from a row

gs.datum.score reads the current row’s score. This expression doubles it:

import genome_spy as gs

double_score = gs.datum.score * 2

Use brackets for field names with spaces or dots: gs.datum["Sample score"].

Compare and combine

Compare values with >, >=, <, <=, ==, or !=. This test means “the score is at least 5 and below 10”:

(gs.datum.score >= 5) & (gs.datum.score < 10)

Use & for “and,” | for “or,” and ~ for “not,” with parentheses around each comparison. Python’s and, or, and not do not work here.

Functions live under gs.expr. For example, gs.expr.sqrt(gs.datum.score) calculates a square root.

Choose between two values

gs.expr.if_() takes a test, the answer when it is true, and the answer when it is false:

score_label = gs.expr.if_(gs.datum.score >= 5, "high", "low")

A score of 5 or more gets the label "high"; other scores get "low". Use None for a missing result. Use gs.expr.if_() instead of Python’s a if test else b inside expressions.

For styling selected marks, see Conditional encodings.

Write an expression as a string

You can also write the calculation using JavaScript-style syntax. These two forms mean the same thing:

double_score = gs.datum.score * 2
double_score = "datum.score * 2"

The GenomeSpy expression reference lists the available operators and functions.

For expressions in channels, see Encodings. To calculate a mark property from a parameter, see Parameters and interaction.

Use expressions with transforms

transform_calculate() stores an expression’s answer in a field. transform_filter() keeps rows that pass a test:

measurements = [
    {"sample": "A", "score": 2},
    {"sample": "B", "score": 5},
    {"sample": "C", "score": 8},
]

chart = (
    gs.Chart(measurements)
    .transform_calculate(doubled=double_score, label=score_label)
    .transform_filter(gs.datum.doubled >= 10)
    .mark_point(filled=True, size=100)
    .encode(x="sample:N", y="doubled:Q", tooltip=["score:Q", "label:N"])
)

This stores double_score and score_label as doubled and label, then keeps rows where doubled is at least 10. See Transforms for more ways to change rows.