Skip to content

Commit a71f1dc

Browse files
committed
CTable.__getitem__ now supports boolean blosc2.LazyExpr / boolean blosc2.NDArray
1 parent c1bc4a2 commit a71f1dc

3 files changed

Lines changed: 54 additions & 2 deletions

File tree

doc/reference/ctable.rst

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,9 @@ explicitly call :meth:`~blosc2.CTable.to_arrow` or iterate with
4242
* ``str`` — column name returns a :class:`Column`; any other string
4343
is interpreted as a boolean expression and behaves like
4444
:meth:`where`.
45+
* boolean :class:`~blosc2.LazyExpr` / :class:`~blosc2.NDArray` —
46+
filtered row view, same as :meth:`where`, e.g.
47+
``t[t.temperature_f > 70]``.
4548
* ``int`` — single row as a namedtuple-like object.
4649
* ``slice`` — row-range view.
4750
* ``list[int]`` / ``ndarray[int]`` — gathered-row view.
@@ -190,11 +193,14 @@ CTable indexing is type-driven::
190193
t[3:8] # row view
191194
t[[1, 4, 7]] # gathered-row view
192195
t[mask] # filtered row view
196+
t[t.amount > 100] # LazyExpr filtered row view, like where()
193197
t[["region", "amount"]] # projected column view
194198

195199
String keys first try exact column-name lookup. If the string is not a
196200
column name, it is interpreted as a boolean expression and behaves like
197-
:meth:`CTable.where`.
201+
:meth:`CTable.where`. Boolean :class:`~blosc2.LazyExpr` and boolean
202+
:class:`~blosc2.NDArray` keys also behave like :meth:`CTable.where`, so computed
203+
column predicates such as ``t[t.temperature_f > 70]`` are supported.
198204

199205
For explicit filtered projection, use::
200206

src/blosc2/ctable.py

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4356,11 +4356,47 @@ def __array__(self, dtype=None, copy=None):
43564356
return arr.copy() if copy else arr
43574357

43584358
def __getitem__(self, key):
4359-
"""Type-driven indexing: column name, boolean expression, row int/slice, mask, or column list."""
4359+
"""Type-driven indexing for columns, rows, projections, and filters.
4360+
4361+
Supported keys are:
4362+
4363+
- ``str``: return a :class:`Column` when it matches a stored or computed
4364+
column name; otherwise evaluate it as a boolean expression via
4365+
:meth:`where`.
4366+
- boolean :class:`blosc2.LazyExpr` or :class:`blosc2.NDArray`: return the
4367+
same filtered view as :meth:`where`, e.g. ``t[t.temperature_f > 70]``.
4368+
- ``int``: return one live row as a namedtuple-like object.
4369+
- ``slice``: return a row-range view.
4370+
- integer array/list: return a gathered-row view.
4371+
- boolean NumPy array/list: return a boolean-mask filtered view.
4372+
- string list: return a column-projection view, equivalent to
4373+
:meth:`select`.
4374+
4375+
Examples
4376+
--------
4377+
Access columns and rows::
4378+
4379+
temps = t["temperature"]
4380+
first = t[0]
4381+
view = t[10:20]
4382+
4383+
Filter rows with a string expression, a stored-column expression, or a
4384+
computed-column expression::
4385+
4386+
warm = t["temperature > 20"]
4387+
warm_active = t[(t.temperature > 20) & t.active]
4388+
hot_fahrenheit = t[t.temperature_f > 70]
4389+
4390+
Project columns::
4391+
4392+
slim = t[["sensor_id", "temperature_f"]]
4393+
"""
43604394
if isinstance(key, str):
43614395
if key in self._cols or key in self._computed_cols:
43624396
return Column(self, key)
43634397
return self.where(key)
4398+
if isinstance(key, (blosc2.NDArray, blosc2.LazyExpr)) and getattr(key, "dtype", None) == np.bool_:
4399+
return self.where(key)
43644400
if isinstance(key, tuple):
43654401
raise TypeError("Tuple indexing is not supported for CTable in V1")
43664402
return self._getitem_row_selector(key)

tests/ctable/test_ctable_computed_cols.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,16 @@ def test_computed_column_where_via_col():
163163
assert len(view) == 3 # 9, 16, 25
164164

165165

166+
def test_getitem_boolean_lazyexpr_matches_where_for_computed_column():
167+
t = _make_invoice_table(5)
168+
t.add_computed_column("total", lambda cols: cols["price"] * cols["qty"])
169+
expr = t.total >= 9
170+
view_getitem = t[expr]
171+
view_where = t.where(expr)
172+
assert len(view_getitem) == len(view_where) == 3
173+
np.testing.assert_array_equal(view_getitem["price"][:], view_where["price"][:])
174+
175+
166176
# ---------------------------------------------------------------------------
167177
# 6. Expression composability
168178
# ---------------------------------------------------------------------------

0 commit comments

Comments
 (0)