Skip to content

Commit

Permalink
feat(): Add trigonometry functions (#1631)
Browse files Browse the repository at this point in the history
  • Loading branch information
dandxy89 committed Nov 1, 2021
1 parent 52c23bf commit 86022d5
Show file tree
Hide file tree
Showing 3 changed files with 261 additions and 2 deletions.
114 changes: 114 additions & 0 deletions py-polars/polars/eager/series.py
Original file line number Diff line number Diff line change
Expand Up @@ -2089,6 +2089,120 @@ def mode(self) -> "Series":
"""
return wrap_s(self._s.mode())

def sin(self) -> "Series":
"""
Compute the element-wise value for Trigonometric sine.
Examples
--------
>>> import numpy as np
>>> s = pl.Series("a", np.array((0., np.pi/2., np.pi)))
>>> s.sin()
shape: (3,)
Series: 'a' [f64]
[
0.0
1
1.2246467991473532e-16
]
"""
return np.sin(self) # type: ignore

def cos(self) -> "Series":
"""
Compute the element-wise value for Trigonometric cosine.
Examples
--------
>>> import numpy as np
>>> s = pl.Series("a", np.array((0., np.pi/2., np.pi)))
>>> s.cos()
shape: (3,)
Series: 'a' [f64]
[
1
6.123233995736766e-17
-1e0
]
"""
return np.cos(self) # type: ignore

def tan(self) -> "Series":
"""
Compute the element-wise value for Trigonometric tangent.
Examples
--------
>>> import numpy as np
>>> s = pl.Series("a", np.array((0., np.pi/2., np.pi)))
>>> s.tan()
shape: (3,)
Series: 'a' [f64]
[
1
6.123233995736766e-17
-1e0
]
"""
return np.tan(self) # type: ignore

def arcsin(self) -> "Series":
"""
Compute the element-wise value for Trigonometric Inverse sine.
Examples
--------
>>> import numpy as np
>>> s = pl.Series("a", np.array((1.0, 0., -1)))
>>> s.arcsin()
shape: (3,)
Series: 'a' [f64]
[
1.5707963267948966
0.0
-1.5707963267948966e0
]
"""
return np.arcsin(self) # type: ignore

def arccos(self) -> "Series":
"""
Compute the element-wise value for Trigonometric Inverse cosine.
Examples
--------
>>> import numpy as np
>>> s = pl.Series("a", np.array((1.0, 0., -1)))
>>> s.arccos()
shape: (3,)
Series: 'a' [f64]
[
0.0
1.5707963267948966
3.141592653589793
]
"""
return np.arccos(self) # type: ignore

def arctan(self) -> "Series":
"""
Compute the element-wise value for Trigonometric Inverse tangent.
Examples
--------
>>> import numpy as np
>>> s = pl.Series("a", np.array((1.0, 0., -1)))
>>> s.arctan()
shape: (3,)
Series: 'a' [f64]
[
0.7853981633974483
0.0
-7.853981633974483e-1
]
"""
return np.arctan(self) # type: ignore

def apply(
self,
func: Callable[[Any], Any],
Expand Down
135 changes: 134 additions & 1 deletion py-polars/polars/lazy/expr.py
Original file line number Diff line number Diff line change
Expand Up @@ -204,6 +204,7 @@ def function(s: "pl.Series") -> "pl.Series":

if "dtype" in kwargs:
return self.map(function, return_dtype=kwargs["dtype"])

return self.map(function, return_dtype=dtype)

def sqrt(self) -> "Expr":
Expand Down Expand Up @@ -1023,7 +1024,7 @@ def map(
Apply a custom python function. This function must produce a `Series`. Any other value will be stored as
null/missing. If you want to apply a function over single values, consider using `apply`.
[read more in the book](https://ritchie46.github.io/polars-book/how_can_i/use_custom_functions.html#lazy)
[read more in the book](https://pola-rs.github.io/polars-book/user-guide/howcani/apply/udfs.html)
Parameters
----------
Expand Down Expand Up @@ -1738,6 +1739,138 @@ def str_concat(self, delimiter: str = "-") -> "Expr": # type: ignore
"""
return wrap_expr(self._pyexpr.str_concat(delimiter))

def sin(self) -> "Expr":
"""
Compute the element-wise value for Trigonometric sine on an array
Returns
-------
Series of dtype Float64
Examples
>>> df = pl.DataFrame({"a": [0.0]})
>>> df.select(pl.col("a").sin())
shape: (1, 1)
┌────────────────────┐
│ a │
│ --- │
│ f64 │
╞════════════════════╡
│ 0.8414709848078965 │
└────────────────────┘
"""
return np.sin(self) # type: ignore

def cos(self) -> "Expr":
"""
Compute the element-wise value for Trigonometric cosine on an array
Returns
-------
Series of dtype Float64
Examples
>>> df = pl.DataFrame({"a": [0.0]})
>>> df.select(pl.col("a").cos())
shape: (1, 1)
┌─────┐
│ a │
│ --- │
│ f64 │
╞═════╡
│ 1 │
└─────┘
"""
return np.cos(self) # type: ignore

def tan(self) -> "Expr":
"""
Compute the element-wise value for Trigonometric tangent on an array
Returns
-------
Series of dtype Float64
Examples
>>> df = pl.DataFrame({"a": [1.0]})
>>> df.select(pl.col("a").tan())
shape: (1, 1)
┌───────────────────┐
│ a │
│ --- │
│ f64 │
╞═══════════════════╡
│ 1.557407724654902 │
└───────────────────┘
"""
return np.tan(self) # type: ignore

def arcsin(self) -> "Expr":
"""
Compute the element-wise value for Trigonometric sine on an array
Returns
-------
Series of dtype Float64
Examples
>>> df = pl.DataFrame({"a": [1.0]})
>>> df.select(pl.col("a").arcsin())
shape: (1, 1)
┌────────────────────┐
│ a │
│ --- │
│ f64 │
╞════════════════════╡
│ 1.5707963267948966 │
└────────────────────┘
"""
return np.arcsin(self) # type: ignore

def arccos(self) -> "Expr":
"""
Compute the element-wise value for Trigonometric cosine on an array
Returns
-------
Series of dtype Float64
Examples
>>> df = pl.DataFrame({"a": [0.0]})
>>> df.select(pl.col("a").arccos())
shape: (1, 1)
┌────────────────────┐
│ a │
│ --- │
│ f64 │
╞════════════════════╡
│ 1.5707963267948966 │
└────────────────────┘
"""
return np.arccos(self) # type: ignore

def arctan(self) -> "Expr":
"""
Compute the element-wise value for Trigonometric tangent on an array
Returns
-------
Series of dtype Float64
Examples
>>> df = pl.DataFrame({"a": [1.0]})
>>> df.select(pl.col("a").arctan())
shape: (1, 1)
┌────────────────────┐
│ a │
│ --- │
│ f64 │
╞════════════════════╡
│ 0.7853981633974483 │
└────────────────────┘
"""
return np.arctan(self) # type: ignore


class ExprListNameSpace:
"""
Expand Down
14 changes: 13 additions & 1 deletion py-polars/tests/test_series.py
Original file line number Diff line number Diff line change
Expand Up @@ -719,7 +719,7 @@ def test_comparisons_int_series_to_float():
assert (srs_int - 1.0).to_list() == [0, 1, 2, 3]
assert (srs_int + 1.0).to_list() == [2, 3, 4, 5]
assert (srs_int * 2.0).to_list() == [2, 4, 6, 8]
# todo: this is inconsistant
# todo: this is inconsistent
assert (srs_int / 2.0).to_list() == [0.5, 1.0, 1.5, 2.0]
assert (srs_int % 2.0).to_list() == [1, 0, 1, 0]
assert (4.0 % srs_int).to_list() == [0, 0, 1, 0]
Expand Down Expand Up @@ -771,3 +771,15 @@ def test_comparisons_bool_series_to_int():
TypeError, match=r"'>' not supported between instances of 'Series' and 'int'"
):
srs_bool > 2


def test_trigonometry_functions():
srs_float = pl.Series("t", [0.0, np.pi])
assert np.allclose(srs_float.sin(), np.array([0.0, 0.0]))
assert np.allclose(srs_float.cos(), np.array([1.0, -1.0]))
assert np.allclose(srs_float.tan(), np.array([0.0, -0.0]))

srs_float = pl.Series("t", [1.0, 0.0, -1])
assert np.allclose(srs_float.arcsin(), np.array([1.571, 0.0, -1.571]), atol=0.01)
assert np.allclose(srs_float.arccos(), np.array([0.0, 1.571, 3.142]), atol=0.01)
assert np.allclose(srs_float.arctan(), np.array([0.785, 0.0, -0.785]), atol=0.01)

0 comments on commit 86022d5

Please sign in to comment.