Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

percentile #19260 #19589

Closed
wants to merge 11 commits into from
88 changes: 88 additions & 0 deletions ivy/data_classes/array/experimental/statistical.py
Original file line number Diff line number Diff line change
Expand Up @@ -686,3 +686,91 @@ def cummin(
dtype=dtype,
out=out,
)

def percentile(
self: ivy.Array,
q: Union[ivy.Array, float],
/,
*,
axis: Optional[Union[Sequence[int], int]] = None,
keepdims: bool = False,
interpolation: str = "nearest",
out: Optional[ivy.Array] = None,
) -> ivy.Array:
"""
ivy.Array instance method variant of ivy.percentile.
This method simply wraps the function,
and so the docstring for ivy.percentile
also applies to this method with
minimal changes.

Parameters
----------
self
Input array.
q
Percentage or sequence of percentile to compute, which must be
between 0 and 100 inclusive.
axis
Axis or axes along which the percentiles are computed. The default
is to compute the percentile(s) along a flattened version of the array.
keepdims
If this is set to True, the axes which are reduced are left in the result
as dimensions with size one. With this option, the result will broadcast
correctly against the original array a.
interpolation
{'nearest', 'linear', 'lower', 'higher', 'midpoint'}. Default value:
'linear'.
This specifies the interpolation method to use when the desired percentile
lies between two data points i < j:
- linear: i + (j - i) * fraction, where fraction is the fractional part of
the index surrounded by i and j.
- lower: i.
- higher: j.
- nearest: i or j, whichever is nearest.
- midpoint: (i + j) / 2. linear and midpoint interpolation do not work with
integer dtypes.
out
optional output array, for writing the result to.

Returns
-------
ret
A (rank(q) + N - len(axis)) dimensional array of same dtype as a, or,
if axis is None, a rank(q) array. The first rank(q) dimensions index
percentiles for different values of q.

Examples
--------
>>> a = ivy.array([[10., 7., 4.], [3., 2., 1.]])
>>> q = ivy.array(0.5)
>>> a.percentile(q)
ivy.array(3.5)

>>> a = ivy.array([[10., 7., 4.], [3., 2., 1.]])
>>> q = 0.5
>>> a.percentile(q)
ivy.array(3.5)

>>> a.percentile(q, axis=0)
ivy.array([6.5, 4.5, 2.5])

>>> a.percentile(q, axis=1)
ivy.array([7., 2.])

>>> a.percentile(q, axis=1, keepdims=True)
ivy.array([[7.],[2.]])

>>> a = ivy.array([1., 2., 3., 4.])
>>> q = ivy.array([0.3, 0.7])
>>> a.percentile(q, interpolation='lower')
ivy.array([1., 3.])
"""
return ivy.percentile(
self._data,
q,
axis=axis,
keepdims=keepdims,
interpolation=interpolation,
out=out,
)
252 changes: 252 additions & 0 deletions ivy/data_classes/container/experimental/statistical.py
Original file line number Diff line number Diff line change
Expand Up @@ -1673,3 +1673,255 @@ def _static_cummin(
dtype=dtype,
out=out,
)

@staticmethod
def static_percentile(
a: Union[ivy.Container, ivy.Array, ivy.NativeArray],
q: Union[ivy.Array, float],
/,
*,
axis: Optional[Union[Sequence[int], int]] = None,
keepdims: bool = False,
interpolation: str = "nearest",
key_chains: Optional[Union[List[str], Dict[str, str]]] = None,
to_apply: bool = True,
prune_unapplied: bool = False,
map_sequences: bool = False,
out: Optional[ivy.Container] = None,
) -> ivy.Container:
"""
ivy.Container static method variant of ivy.percentile.
This method simply wraps the function, and so the docstring
for ivy.percentile also applies to this
method with minimal changes.

Parameters
----------
a
Input container including arrays.
q
Percentile or sequence of percentiles to compute, which must be
between 0 and 100 inclusive.
axis
Axis or axes along which the percentiles are computed. The default
is to compute the percentile(s) along a flattened version of the array.
keepdims
If this is set to True, the axes which are reduced are left in the result
as dimensions with size one. With this option, the result will broadcast
correctly against the original array a.
interpolation
{'nearest', 'linear', 'lower', 'higher', 'midpoint'}. Default value:
'linear'.
This specifies the interpolation method to use when the desired percentile
lies between two data points i < j:
- linear: i + (j - i) * fraction, where fraction is the fractional part of
the index surrounded by i and j.
- lower: i.
- higher: j.
- nearest: i or j, whichever is nearest.
- midpoint: (i + j) / 2. linear and midpoint interpolation do not work with
integer dtypes.
out
optional output array, for writing the result to.

Returns
-------
ret
Container with (rank(q) + N - len(axis)) dimensional arrays of same dtype
as input arrays in the container, or, if axis is None, rank(q) arrays. The
first rank(q) dimensions index percentiles for different values of q.

Examples
--------
With one :class:`ivy.Container` input:

>>> a = ivy.Container(x=ivy.array([[10., 7., 4.], [3., 2., 1.]]),
y=ivy.array([1., 2., 3., 4.]))
>>> q = 0.5
>>> b = ivy.Container.percentile(a, q)
>>> print(b)
{
x: 3.5,
y: 2.5
}

>>> a = ivy.Container(x=ivy.array([[10., 7., 4.], [3., 2., 1.]]),
y=ivy.array([1., 2., 3., 4.]))
>>> q = ivy.array([0.5, 0.75])
>>> b = ivy.Container.static_percentile(a, q)
>>> print(b)
{
x: ivy.array([3.5, 6.25]),
y: ivy.array([2.5, 3.25])
}

>>> a = ivy.Container(x=ivy.array([[10., 7., 4.], [3., 2., 1.]]),
y=ivy.array([1., 2., 3., 4.]))
>>> q = ivy.array([0.5, 0.75])
>>> b = ivy.Container.static_percentile(a, q, axis = 0)
>>> print(b)
{
x: ivy.array([[6.5, 4.5, 2.5],
[8.25, 5.75, 3.25]]),
y: ivy.array([2.5, 3.25])
}

>>> a = ivy.Container(x=ivy.array([[10., 7., 4.], [3., 2., 1.]]))
>>> b = ivy.Container.static_percentile(a, q, axis = 1, keepdims=True)
>>> print(b)
{
x: ivy.array([[[7.],
[2.]],
[[8.5],
[2.5]]])
}

>>> a = ivy.Container(x=ivy.array([[10., 7., 4.], [3., 2., 1.]]),
y=ivy.array([1., 2., 3., 4.]))
>>> q = ivy.array([0.3, 0.7])
>>> b = ivy.Container.static_percentile(a, q, axis = 0, interpolation="lower")
>>> print(b)
{
x: ivy.array([[3., 2., 1.],
[3., 2., 1.]]),
y: ivy.array([1., 3.])
}
"""
return ContainerBase.cont_multi_map_in_function(
"percentile",
a,
q,
axis=axis,
keepdims=keepdims,
interpolation=interpolation,
key_chains=key_chains,
to_apply=to_apply,
prune_unapplied=prune_unapplied,
map_sequences=map_sequences,
out=out,
)

def percentile(
self: ivy.Container,
q: Union[ivy.Array, float],
/,
*,
axis: Optional[Union[Sequence[int], int]] = None,
keepdims: bool = False,
interpolation: str = "nearest",
key_chains: Optional[Union[List[str], Dict[str, str]]] = None,
to_apply: bool = True,
prune_unapplied: bool = False,
map_sequences: bool = False,
out: Optional[ivy.Container] = None,
) -> ivy.Container:
"""
ivy.Container instance method variant of ivy.percentile.
This method simply wraps the function, and so the docstring
for ivy.percentile also applies to this
method with minimal changes.

Parameters
----------
a
Input container including arrays.
q
Percentile or sequence of percentiles to compute, which must be
between 0 and 100 inclusive.
axis
Axis or axes along which the percentiles are computed. The default
is to compute the percentile(s) along a flattened version of the array.
keepdims
If this is set to True, the axes which are reduced are left in the result
as dimensions with size one. With this option, the result will broadcast
correctly against the original array a.
interpolation
{'nearest', 'linear', 'lower', 'higher', 'midpoint'}. Default value:
'linear'.
This specifies the interpolation method to use when the desired percentile
lies between two data points i < j:
- linear: i + (j - i) * fraction, where fraction is the fractional part of
the index surrounded by i and j.
- lower: i.
- higher: j.
- nearest: i or j, whichever is nearest.
- midpoint: (i + j) / 2. linear and midpoint interpolation do not work with
integer dtypes.
out
optional output array, for writing the result to.

Returns
-------
ret
Container with (rank(q) + N - len(axis)) dimensional arrays of same dtype
as input arrays in the container, or, if axis is None, rank(q) arrays. The
first rank(q) dimensions index percentile for different values of q.

Examples
--------
With one :class:`ivy.Container` input:

>>> a = ivy.Container(x=ivy.array([[10., 7., 4.], [3., 2., 1.]]),\
y=ivy.array([1., 2., 3., 4.]))
>>> q = 0.5
>>> b = a.percentile(q)
>>> print(b)
{
x: 3.5,
y: 2.5
}

>>> a = ivy.Container(x=ivy.array([[10., 7., 4.], [3., 2., 1.]]),
y=ivy.array([1., 2., 3., 4.]))
>>> q = ivy.array([0.5, 0.75])
>>> b = a.percentile(q)
>>> print(b)
{
x: ivy.array([3.5, 6.25]),
y: ivy.array([2.5, 3.25])
}

>>> a = ivy.Container(x=ivy.array([[10., 7., 4.], [3., 2., 1.]]),
y=ivy.array([1., 2., 3., 4.]))
>>> q = ivy.array([0.5, 0.75])
>>> b = a.percentile(q, axis = 0)
>>> print(b)
{
x: ivy.array([[6.5, 4.5, 2.5],
[8.25, 5.75, 3.25]]),
y: ivy.array([2.5, 3.25])
}

>>> a = ivy.Container(x=ivy.array([[10., 7., 4.], [3., 2., 1.]]))
>>> b = a.percentile(q, axis = 1, keepdims=True)
>>> print(b)
{
x: ivy.array([[[7.],
[2.]],
[[8.5],
[2.5]]])
}

>>> a = ivy.Container(x=ivy.array([[10., 7., 4.], [3., 2., 1.]]),
y=ivy.array([1., 2., 3., 4.]))
>>> q = ivy.array([0.3, 0.7])
>>> b = a.percentile(q, axis = 0, interpolation="lower")
>>> print(b)
{
x: ivy.array([[3., 2., 1.],
[3., 2., 1.]]),
y: ivy.array([1., 3.])
}
"""
return self.static_percentile(
self,
q,
axis=axis,
keepdims=keepdims,
interpolation=interpolation,
key_chains=key_chains,
to_apply=to_apply,
prune_unapplied=prune_unapplied,
map_sequences=map_sequences,
out=out,
)
22 changes: 22 additions & 0 deletions ivy/functional/backends/jax/experimental/statistical.py
Original file line number Diff line number Diff line change
Expand Up @@ -400,3 +400,25 @@ def igamma(
out: Optional[JaxArray] = None,
) -> JaxArray:
return jlax.igamma(a=a, x=x)


@with_unsupported_dtypes(
{"0.4.13 and below": ("bfloat16",)},
backend_version,
)
def percentile(
a: JaxArray,
q: Union[float, JaxArray],
/,
*,
axis: Optional[Union[int, Sequence[int]]] = None,
interpolation: str = "nearest",
keepdims: bool = False,
out: Optional[JaxArray] = None,
) -> JaxArray:
if isinstance(axis, list):
axis = tuple(axis)

return jnp.percentile(
a, q, axis=axis, method=interpolation, keepdims=keepdims, out=out
)
13 changes: 13 additions & 0 deletions ivy/functional/backends/mxnet/experimental/statistical.py
Original file line number Diff line number Diff line change
Expand Up @@ -103,3 +103,16 @@ def cov(
dtype: Optional[type] = None,
) -> None:
raise IvyNotImplementedException()


def percentile(
a: Union[(None, mx.ndarray.NDArray)],
q: Union[(None, float)],
/,
*,
axis: Optional[Union[(int, Sequence[int])]] = None,
interpolation: str = "nearest",
keepdims: bool = False,
out: Optional[Union[(None, mx.ndarray.NDArray)]] = None,
) -> Union[(None, mx.ndarray.NDArray)]:
raise IvyNotImplementedException()
Loading
Loading