lazybear

API Reference

LazyBearFrame

The main object representing a lazy SQL query. It is immutable; every transformation returns a new LazyBearFrame.

Properties

columns

engine

Transformations

select(*items)

filter(predicate)

with_columns(*exprs, **named)

sort(by, *more_by, descending=False)

order_by(*keys)

limit(n)

join(other, on=None, *, left_on=None, right_on=None, how='inner', suffix=None, prefix=None, apply_to_all=True, duplicate_columns='rename')

Join this frame with another LazyBearFrame using one or more equality keys.

Both frames must use the same database server.

Specifying join keys

Use on when the key names are the same:

users.join(accounts, on='user_id')
users.join(accounts, on=['user_id', 'region_id'])

Use left_on and right_on when the key names differ:

users.join(
    accounts,
    left_on='id',
    right_on='user_id',
)

A mapping can also associate differently named keys:

users.join(
  accounts,
  on={'id': 'user_id'},
)

Do not combine on with left_on or right_on.

Join strategies

how supports:

Right-column naming

When right-side column names overlap with left-side names:

For example:

users.join(orders, on={'id': 'user_id'}, prefix='order_')

produces right-side names such as order_id, order_user_id, and order_amount.

To rename only overlapping columns:

users.join(
    orders,
    on={'id': 'user_id'},
    suffix='_order',
    apply_to_all=False,
)

Set duplicate_columns='drop' to omit right-side columns that would otherwise be renamed:

users.join(
    orders,
    on={'id': 'user_id'},
    duplicate_columns='drop',
)

When the same key name is used on both sides, such as on='id', the duplicate right key is omitted automatically.

See the complete join documentation.


join_where(other, *predicates, how='inner', suffix=None, prefix=None, apply_to_all=True, duplicate_columns='rename')

Join this frame with another LazyBearFrame using arbitrary equality or inequality predicates.

This is useful for non-equi joins, including effective-date and interval matching:

orders.join_where(
    prices,
    col('product_id') == col('product_id_right'),
    col('order_date') >= col('valid_from'),
    col('order_date') <= col('valid_to'),
)

This is equivalent to:

ON orders.product_id = prices.product_id
AND orders.order_date >= prices.valid_from
AND orders.order_date <= prices.valid_to

Multiple predicates are combined with AND. To express alternatives within one predicate, combine expressions with |.

Join strategies

how supports:

A full join is not supported by join_where.

Referencing right-side columns

Predicates use the right-column names produced by the prefix and suffix rules.

When a column exists on both sides, the right-side reference receives a generated suffix by default:

col('id') == col('id_right')

Do not write:

# WRONG!
col('id') == col('id')

Both expressions resolve to the left-side id, producing left.id = left.id rather than a comparison between frames.

If an explicit prefix or suffix is supplied, use the resulting names in the predicates. Because explicit naming applies to all right-side columns by default, this example suffixes every right-side reference:

orders.join_where(
    prices,
    col('product_id') == col('product_id_price'),
    col('order_date') >= col('valid_from_price'),
    col('order_date') <= col('valid_to_price'),
    suffix='_price',  # by default, suffix applies to all columns
)

To rename only overlapping right-side columns:

orders.join_where(
    prices,
    col('product_id') == col('product_id_price'),
    col('order_date') >= col('valid_from'),
    col('order_date') <= col('valid_to'),
    suffix='_price',
    apply_to_all=False,
)

prefix takes precedence over suffix when both are supplied.

Dropping duplicate columns

Set duplicate_columns='drop' to omit selected right-side columns from the result:

orders.join_where(
    prices,
    col('product_id') == col('product_id_right'),
    col('order_date') >= col('valid_from'),
    col('order_date') <= col('valid_to'),
    duplicate_columns='drop',
)

Dropped right-side columns remain available under their renamed names while the join predicates are evaluated.

The result row order is not guaranteed. Call sort or order_by when deterministic ordering is required.

See equality and range-join examples.

group_by(*keys)

GroupedLazyBearFrame

A frame representing grouped data, returned by LazyBearFrame.group_by.

agg(**aggregations)

lf.group_by('department').agg(
    total_salary=('salary', 'sum'),
    avg_age=(col('age'), 'mean'),
    employee_count=('id', 'count')
)

Execution & Materialization

collect(limit=None, infer_schema_length=200)

to_arrow(limit=None)

collect_batches(chunk_size=10_000)

iter_rows(named=False, chunk_size=10_000)

explain()

I/O Helpers

write_parquet(file, chunk_size=None, start_index=0, **kwargs)

write_csv(file, chunk_size=None, **kwargs)

Advanced

to_select()

Scanning Functions: Create Temporary Tables on the Server

This has limited testing.

scan_table(table_name, engine, schema=None, lowercase=True)

scan_sql_query(query, engine, columns=None)

scan_df(df, engine, table_name=None)