Skip to content

Commit

Permalink
expr.std
Browse files Browse the repository at this point in the history
  • Loading branch information
MarcoGorelli committed Apr 3, 2024
1 parent 19f16f2 commit 2177628
Show file tree
Hide file tree
Showing 7 changed files with 26 additions and 14 deletions.
2 changes: 2 additions & 0 deletions docs/extending.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ If you want your own library to be recognised too, you can either:
functions from `narwhals` (e.g. `narwhals.col`, `narwhals.concat`, ...)
- `Series.__narwhals_series__`: return an object which implements public methods
from `Narwhals.Series`
- `Series.__narwhals_namespace__`: return an object which implements public top-level
functions from `narwhals` (e.g. `narwhals.col`, `narwhals.concat`, ...)

If your library doesn't distinguish between lazy and eager, then it's OK for your dataframe
object to implement both `__narwhals_dataframe__` and `__narwhals_lazyframe__`. In fact,
Expand Down
2 changes: 1 addition & 1 deletion narwhals/_pandas_like/dataframe.py
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,7 @@ def sort(
*more_by: str,
descending: bool | Sequence[bool] = False,
) -> Self:
flat_keys = flatten([*flatten(by), *more_by])
flat_keys = flatten([*flatten([by]), *more_by])
df = self._dataframe
if isinstance(descending, bool):
ascending: bool | list[bool] = not descending
Expand Down
3 changes: 3 additions & 0 deletions narwhals/_pandas_like/expr.py
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,9 @@ def sum(self) -> Self:
def mean(self) -> Self:
return register_expression_call(self, "mean")

def std(self) -> Self:
return register_expression_call(self, "std")

def any(self) -> Self:
return register_expression_call(self, "any")

Expand Down
6 changes: 5 additions & 1 deletion narwhals/_pandas_like/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -94,8 +94,12 @@ def maybe_evaluate_expr(df: PandasDataFrame, arg: Any) -> Any:
def parse_into_exprs(
implementation: str,
*exprs: IntoPandasExpr | Iterable[IntoPandasExpr],
**named_exprs: IntoPandasExpr,
) -> list[PandasExpr]:
return [parse_into_expr(implementation, into_expr) for into_expr in flatten(exprs)]
out = [parse_into_expr(implementation, into_expr) for into_expr in flatten(exprs)]
for name, expr in named_exprs.items():
out.append(parse_into_expr(implementation, expr).alias(name))
return out


def parse_into_expr(implementation: str, into_expr: IntoPandasExpr) -> PandasExpr:
Expand Down
3 changes: 3 additions & 0 deletions narwhals/expression.py
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,9 @@ def all(self) -> Expr:
def mean(self) -> Expr:
return self.__class__(lambda plx: self._call(plx).mean())

def std(self) -> Expr:
return self.__class__(lambda plx: self._call(plx).std())

def sum(self) -> Expr:
return self.__class__(lambda plx: self._call(plx).sum())

Expand Down
2 changes: 2 additions & 0 deletions tests/test_common.py
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@ def test_add(df_raw: Any) -> None:
result = df.with_columns(
c=nw.col("a") + nw.col("b"),
d=nw.col("a") - nw.col("a").mean(),
e=nw.col("a") - nw.col("a").std(),
)
result_native = nw.to_native(result)
expected = {
Expand All @@ -99,6 +100,7 @@ def test_add(df_raw: Any) -> None:
"z": [7.0, 8.0, 9.0],
"c": [5, 7, 8],
"d": [-1.0, 1.0, 0.0],
"e": [0.0, 2.0, 1.0],
}
compare_dicts(result_native, expected)

Expand Down
22 changes: 10 additions & 12 deletions tests/tpch_q1_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -103,18 +103,16 @@ def test_q1_w_generic_funcs(library: str) -> None:
)
.group_by(["l_returnflag", "l_linestatus"])
.agg(
[
nw.sum("l_quantity").alias("sum_qty"),
nw.sum("l_extendedprice").alias("sum_base_price"),
(nw.col("l_extendedprice") * (1 - nw.col("l_discount")))
.sum()
.alias("sum_disc_price"),
nw.col("charge").sum().alias("sum_charge"),
nw.mean("l_quantity").alias("avg_qty"),
nw.mean("l_extendedprice").alias("avg_price"),
nw.mean("l_discount").alias("avg_disc"),
nw.len().alias("count_order"),
],
nw.sum("l_quantity").alias("sum_qty"),
nw.sum("l_extendedprice").alias("sum_base_price"),
(nw.col("l_extendedprice") * (1 - nw.col("l_discount")))
.sum()
.alias("sum_disc_price"),
nw.col("charge").sum().alias("sum_charge"),
nw.mean("l_quantity").alias("avg_qty"),
nw.mean("l_extendedprice").alias("avg_price"),
nw.mean("l_discount").alias("avg_disc"),
count_order=nw.len(),
)
.sort(["l_returnflag", "l_linestatus"])
)
Expand Down

0 comments on commit 2177628

Please sign in to comment.