Skip to content

Commit

Permalink
feat(api): allow grouping by scalar values (#9451)
Browse files Browse the repository at this point in the history
  • Loading branch information
cpcloud authored Jun 27, 2024
1 parent c1e2002 commit 14f1821
Show file tree
Hide file tree
Showing 4 changed files with 46 additions and 18 deletions.
36 changes: 36 additions & 0 deletions ibis/backends/tests/test_aggregation.py
Original file line number Diff line number Diff line change
Expand Up @@ -1553,3 +1553,39 @@ def test_group_by_expr(backend, con):
dict(n="int32", c="int64")
)
backend.assert_frame_equal(result, expected)


@pytest.mark.parametrize(
"value",
[
ibis.literal("a"),
param(
ibis.null("str"),
marks=[
pytest.mark.notimpl(
["pandas", "dask"],
reason="nulls are discarded by default in group bys",
raises=IndexError,
),
pytest.mark.notyet(
["druid"],
raises=PyDruidProgrammingError,
reason=(
"druid resists typed nulls for reasons unrelated to grouping,"
" and this is compiled as an untyped NULL "
"which of course isn't allowed in a group by"
),
),
],
),
],
ids=["string", "null"],
)
@pytest.mark.notyet(
["mssql"], raises=PyODBCProgrammingError, reason="not supported by the database"
)
def test_group_by_scalar(alltypes, df, value):
expr = alltypes.group_by(key=value).agg(n=lambda t: t.count())
result = expr.execute()
n = result["n"].values[0].item()
assert n == len(df)
2 changes: 1 addition & 1 deletion ibis/expr/operations/relations.py
Original file line number Diff line number Diff line change
Expand Up @@ -299,7 +299,7 @@ class Aggregate(Relation):
"""Aggregate a table by a set of group by columns and metrics."""

parent: Relation
groups: FrozenOrderedDict[str, Unaliased[Column]]
groups: FrozenOrderedDict[str, Unaliased[Value]]
metrics: FrozenOrderedDict[str, Unaliased[Scalar]]

def __init__(self, parent, groups, metrics):
Expand Down
11 changes: 3 additions & 8 deletions ibis/expr/types/groupby.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,16 +16,16 @@

from __future__ import annotations

from typing import TYPE_CHECKING
from typing import TYPE_CHECKING, Annotated

from public import public

import ibis
import ibis.common.exceptions as com
import ibis.expr.datatypes as dt
import ibis.expr.operations as ops
import ibis.expr.types as ir
from ibis.common.grounds import Concrete
from ibis.common.patterns import Length # noqa: TCH001
from ibis.common.typing import VarTuple # noqa: TCH001
from ibis.expr.rewrites import rewrite_window_input

Expand All @@ -38,15 +38,10 @@ class GroupedTable(Concrete):
"""An intermediate table expression to hold grouping information."""

table: ops.Relation
groupings: VarTuple[ops.Column]
groupings: Annotated[VarTuple[ops.Value], Length(at_least=1)]
orderings: VarTuple[ops.SortKey] = ()
havings: VarTuple[ops.Value[dt.Boolean]] = ()

def __init__(self, groupings, **kwargs):
if not groupings:
raise com.IbisInputError("No group keys provided")
super().__init__(groupings=groupings, **kwargs)

def __getitem__(self, args):
# Shortcut for projection with window functions
return self.select(*args)
Expand Down
15 changes: 6 additions & 9 deletions ibis/tests/expr/test_table.py
Original file line number Diff line number Diff line change
Expand Up @@ -846,9 +846,13 @@ def test_groupby_convenience(table):
assert_equal(expr, expected)


@pytest.mark.parametrize("group", [[], (), None])
@pytest.mark.parametrize(
"group",
[[], (), None, s.startswith("over9000")],
ids=["list", "tuple", "none", "selector"],
)
def test_group_by_nothing(table, group):
with pytest.raises(com.IbisInputError):
with pytest.raises(ValidationError):
table.group_by(group)


Expand Down Expand Up @@ -1695,13 +1699,6 @@ def test_group_by_key_function():
assert expr.columns == ["new_key", "foo"]


def test_group_by_no_keys():
t = ibis.table([("a", "timestamp"), ("b", "string"), ("c", "double")])

with pytest.raises(com.IbisInputError):
t.group_by(s.startswith("x")).aggregate(foo=t.c.mean())


def test_unbound_table_name():
t = ibis.table([("a", "timestamp")])
name = t.op().name
Expand Down

0 comments on commit 14f1821

Please sign in to comment.