Interactive Expressions

Internally Blaze is abstract; this limits interactivity. Blaze interactive expressions resolve this issue and provide a smooth experience to handling foreign data.

Expressions with Data

Internally Blaze separates the intent of the computation from the data/backend. While powerful, this abstract separation limits interactivity, one of the core goals of Blaze.

Blaze interactive expressions are like normal expressions but their leaves may hold on to a concrete data resource (like a DataFrame or SQL database.) This embeds a specific data context, providing user interface improvements at the cost of full generality.


We create an interactive expression by calling the data constructor on any object or URI with which Blaze is familiar.

>>> from blaze import data, Symbol
>>> from blaze.utils import example
>>> db = data('sqlite:///%s' % example('iris.db'))  # an interactive expression
>>> db.iris
    sepal_length  sepal_width  petal_length  petal_width      species
0            5.1          3.5           1.4          0.2  Iris-setosa
1            4.9          3.0           1.4          0.2  Iris-setosa
2            4.7          3.2           1.3          0.2  Iris-setosa
3            4.6          3.1           1.5          0.2  Iris-setosa
4            5.0          3.6           1.4          0.2  Iris-setosa
5            5.4          3.9           1.7          0.4  Iris-setosa
6            4.6          3.4           1.4          0.3  Iris-setosa
7            5.0          3.4           1.5          0.2  Iris-setosa
8            4.4          2.9           1.4          0.2  Iris-setosa
9            4.9          3.1           1.5          0.1  Iris-setosa

>>> db.iris.species.<tab>  
db.iris.species.columns       db.iris.species.max
db.iris.species.count         db.iris.species.min
db.iris.species.count_values  db.iris.species.ndim
db.iris.species.distinct      db.iris.species.nunique
db.iris.species.dshape        db.iris.species.relabel
db.iris.species.expr          db.iris.species.resources
db.iris.species.fields        db.iris.species.schema
db.iris.species.head          db.iris.species.shape
db.iris.species.isidentical   db.iris.species.sort
db.iris.species.label         db.iris.species.species          db.iris.species.to_html

>>> db.iris.species.distinct()
0      Iris-setosa
1  Iris-versicolor
2   Iris-virginica

In the case above db is a Symbol, just like any normal Blaze leaf expresion

>>> isinstance(db, Symbol)

But db has one additional field, which points to a SQLAlchemy Table.

<sqlalchemy.Table at 0x7f0f64ffbdd0>

Compute calls including db may omit the customary namespace, e.g.

>>> from blaze import compute
>>> expr = db.iris.species.distinct()

>>> # compute(expr, {db: some_sql_object})  # Usually provide a namespace
>>> compute(expr)                             
['Iris-setosa', 'Iris-versicolor', 'Iris-virginica']

This implicit namespace can be found with the ._resources method

>>> expr._resources()                          
{db: <sqlalchemy.Table object>}

Additionally, we override the __repr__ and _repr_html_ methods to include calls to compute. This way, whenever an expression is printed to the screen a small computation is done to print the computed data instead.

As an example, this __repr__ function looks something like the following:

from odo import odo
from pandas import DataFrame
from blaze import Expr

def __repr__(expr):
    expr = expr.head(10)         # Only need enough to print to the screen
    result = compute(expr)       # Do the work necessary to get a result
    df = odo(result, DataFrame) # Shove into a DataFrame
    return repr(df)              # Use pandas' nice printing

Expr.__repr__ = __repr__   # Override normal __repr__ method

This provides smooth interactive feel of interactive expressions. Work is only done when an expression is printed to the screen and excessive results are avoided by wrapping all computations in a .head(10).