Skip to content

Commit

Permalink
python: add log, log10, exp
Browse files Browse the repository at this point in the history
  • Loading branch information
ritchie46 committed Dec 2, 2021
1 parent cf3da38 commit 78f2de5
Show file tree
Hide file tree
Showing 7 changed files with 84 additions and 1 deletion.
3 changes: 3 additions & 0 deletions py-polars/docs/source/reference/expression.rst
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,9 @@ Computations
Expr.arcsin
Expr.arccos
Expr.arctan
Expr.log
Expr.log10
Expr.exp

Manipulation/ selection
-----------------------
Expand Down
3 changes: 3 additions & 0 deletions py-polars/docs/source/reference/series.rst
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,9 @@ Computations
Series.arcsin
Series.arccos
Series.arctan
Series.log
Series.log10
Series.exp

Manipulation/ selection
-----------------------
Expand Down
21 changes: 21 additions & 0 deletions py-polars/polars/internals/expr.py
Original file line number Diff line number Diff line change
Expand Up @@ -197,6 +197,27 @@ def sqrt(self) -> "Expr":
"""
return self ** 0.5

def log(self) -> "Expr":
"""
Natural logarithm, element-wise.
The natural logarithm log is the inverse of the exponential function, so that log(exp(x)) = x.
The natural logarithm is logarithm in base e.
"""
return np.log(self) # type: ignore

def log10(self) -> "Expr":
"""
Return the base 10 logarithm of the input array, element-wise.
"""
return np.log10(self) # type: ignore

def exp(self) -> "Expr":
"""
Return the exponential element-wise
"""
return np.exp(self) # type: ignore

def alias(self, name: str) -> "Expr":
"""
Rename the output of an expression.
Expand Down
2 changes: 1 addition & 1 deletion py-polars/polars/internals/lazy_functions.py
Original file line number Diff line number Diff line change
Expand Up @@ -1135,7 +1135,7 @@ def collect_all(


def select(
exprs: Union[str, "pli.Expr", Sequence[str], Sequence["pli.Expr"]]
exprs: Union[str, "pli.Expr", Sequence[str], Sequence["pli.Expr"], "pli.Series"]
) -> "pli.DataFrame":
"""
Run polars expressions without a context.
Expand Down
21 changes: 21 additions & 0 deletions py-polars/polars/internals/series.py
Original file line number Diff line number Diff line change
Expand Up @@ -559,6 +559,27 @@ def sqrt(self) -> "Series":
"""
return self ** 0.5

def log(self) -> "Series":
"""
Natural logarithm, element-wise.
The natural logarithm log is the inverse of the exponential function, so that log(exp(x)) = x.
The natural logarithm is logarithm in base e.
"""
return np.log(self) # type: ignore

def log10(self) -> "Series":
"""
Return the base 10 logarithm of the input array, element-wise.
"""
return np.log10(self) # type: ignore

def exp(self) -> "Series":
"""
Return the exponential element-wise
"""
return np.exp(self) # type: ignore

def drop_nulls(self) -> "Series":
"""
Create a new Series that copies data from this Series without null values.
Expand Down
18 changes: 18 additions & 0 deletions py-polars/tests/test_exprs.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
import numpy as np

import polars as pl
from polars import testing


def test_horizontal_agg(fruits_cars: pl.DataFrame) -> None:
Expand Down Expand Up @@ -31,3 +34,18 @@ def test_cumcount() -> None:

assert out["foo"][0].to_list() == [0, 1, 2, 3]
assert out["foo"][1].to_list() == [0, 1]


def test_log_exp() -> None:
a = pl.Series("a", [1, 100, 1000])
out = pl.select(a.log10()).to_series()
expected = pl.Series("a", [0.0, 2.0, 3.0])
testing.assert_series_equal(out, expected)

out = pl.select(a.log()).to_series()
expected = pl.Series("a", np.log(a.to_numpy()))
testing.assert_series_equal(out, expected)

out = pl.select(a.exp()).to_series()
expected = pl.Series("a", np.exp(a.to_numpy()))
testing.assert_series_equal(out, expected)
17 changes: 17 additions & 0 deletions py-polars/tests/test_series.py
Original file line number Diff line number Diff line change
Expand Up @@ -1076,3 +1076,20 @@ def test_nested_list_types_preserved() -> None:
srs1 = pl.Series([pl.Series([3, 4, 5, 6], dtype=expected_dtype) for _ in range(5)])
for srs2 in srs1:
assert srs2.dtype == expected_dtype


def test_log_exp() -> None:
a = pl.Series("a", [1, 100, 1000])

out = a.log10()
expected = pl.Series("a", [0.0, 2.0, 3.0])
testing.assert_series_equal(out, expected)
a = pl.Series("a", [1, 100, 1000])

out = a.log()
expected = pl.Series("a", np.log(a.to_numpy()))
testing.assert_series_equal(out, expected)

out = a.exp()
expected = pl.Series("a", np.exp(a.to_numpy()))
testing.assert_series_equal(out, expected)

0 comments on commit 78f2de5

Please sign in to comment.