Skip to content

Commit 8cc142b

Browse files
0x0L0x0L
0x0L
authored and
0x0L
committed
initial support for rank
1 parent 4caae2e commit 8cc142b

File tree

5 files changed

+58
-1
lines changed

5 files changed

+58
-1
lines changed

doc/api-hidden.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,7 @@
9191
DataArray.T
9292
DataArray.cumsum
9393
DataArray.cumprod
94+
DataArray.rank
9495

9596
ufuncs.angle
9697
ufuncs.arccos

doc/api.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -312,6 +312,7 @@ Computation
312312
:py:attr:`~DataArray.T`
313313
:py:attr:`~DataArray.cumsum`
314314
:py:attr:`~DataArray.cumprod`
315+
:py:attr:`~DataArray.rank`
315316

316317
**Grouped operations**:
317318
:py:attr:`~core.groupby.DataArrayGroupBy.assign_coords`

doc/whats-new.rst

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -208,6 +208,9 @@ Enhancements
208208
(:issue:`1485`).
209209
By `Joe Hamman <https://github.com/jhamman>`_.
210210

211+
- New :py:meth:`~xarray.DataArray.rank`. Requires bottleneck (:issue:`1731`).
212+
By `0x0L <https://github.com/0x0L>`_.
213+
211214
**Performance improvements**
212215

213216
- :py:func:`~xarray.concat` was computing variables that aren't in memory

xarray/core/dataarray.py

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
from .accessors import DatetimeAccessor
2020
from .alignment import align, reindex_like_indexers
2121
from .common import AbstractArray, BaseDataObject
22+
from .computation import apply_ufunc
2223
from .coordinates import (DataArrayCoordinates, LevelCoordinatesSource,
2324
Indexes)
2425
from .dataset import Dataset, merge_indexes, split_indexes
@@ -1958,6 +1959,42 @@ def quantile(self, q, dim=None, interpolation='linear', keep_attrs=False):
19581959
interpolation=interpolation)
19591960
return self._from_temp_dataset(ds)
19601961

1962+
def rank(self, dim):
1963+
"""Ranks the data.
1964+
1965+
Equal values are assigned a rank that is the average of the ranks that
1966+
would have been otherwise assigned to all of the values within that set.
1967+
Ranks begin at 1, not 0.
1968+
1969+
NaNs in the input array are returned as NaNs.
1970+
1971+
Parameters
1972+
----------
1973+
dim : str, optional
1974+
1975+
Returns
1976+
-------
1977+
ranked : DataArray
1978+
DataArray with the same coordinates and dtype 'float64'.
1979+
1980+
Examples
1981+
--------
1982+
1983+
>>> arr = xr.DataArray([5, 6, 7], dims='x')
1984+
>>> arr.rank('x')
1985+
<xarray.DataArray (x: 3)>
1986+
array([ 1., 2., 3.])
1987+
Dimensions without coordinates: x
1988+
"""
1989+
import bottleneck as bn
1990+
axis = self.get_axis_num(dim)
1991+
func = bn.nanrankdata if self.dtype.kind is 'f' else bn.rankdata
1992+
return apply_ufunc(func, self,
1993+
dask='parallelized',
1994+
keep_attrs=True,
1995+
output_dtypes=[np.float_],
1996+
kwargs=dict(axis=axis)).transpose(*self.dims)
1997+
19611998

19621999
# priority most be higher than Variable to properly work with binary ufuncs
19632000
ops.inject_all_ops_and_reduce_methods(DataArray, priority=60)

xarray/tests/test_dataarray.py

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
from xarray.tests import (
2020
TestCase, ReturnItem, source_ndarray, unittest, requires_dask,
2121
assert_identical, assert_equal, assert_allclose, assert_array_equal,
22-
raises_regex, requires_scipy)
22+
raises_regex, requires_scipy, requires_bottleneck)
2323

2424

2525
class TestDataArray(TestCase):
@@ -2976,6 +2976,21 @@ def test_sortby(self):
29762976
actual = da.sortby(['x', 'y'])
29772977
self.assertDataArrayEqual(actual, expected)
29782978

2979+
@requires_bottleneck
2980+
def test_rank(self):
2981+
# floats
2982+
ar = DataArray([[3, 4, np.nan, 1]])
2983+
expect_0 = DataArray([[1, 1, np.nan, 1]])
2984+
expect_1 = DataArray([[2, 3, np.nan, 1]])
2985+
self.assertDataArrayEqual(ar.rank('dim_0'), expect_0)
2986+
self.assertDataArrayEqual(ar.rank('dim_1'), expect_1)
2987+
# int
2988+
x = DataArray([3,2,1])
2989+
self.assertDataArrayEqual(x.rank('dim_0'), x)
2990+
# str
2991+
y = DataArray(['c', 'b', 'a'])
2992+
self.assertDataArrayEqual(y.rank('dim_0'), x)
2993+
29792994

29802995
@pytest.fixture(params=[1])
29812996
def da(request):

0 commit comments

Comments
 (0)