|
16 | 16 | from pandas.tests.series.common import TestData
|
17 | 17 | from pandas._libs.tslib import iNaT
|
18 | 18 | from pandas._libs.algos import Infinity, NegInfinity
|
| 19 | +from itertools import chain |
| 20 | +import pandas.util._test_decorators as td |
19 | 21 |
|
20 | 22 |
|
21 | 23 | class TestSeriesRank(TestData):
|
@@ -257,38 +259,52 @@ def _check(s, expected, method='average'):
|
257 | 259 | series = s if dtype is None else s.astype(dtype)
|
258 | 260 | _check(series, results[method], method=method)
|
259 | 261 |
|
260 |
| - def test_rank_tie_methods_on_infs_nans(self): |
| 262 | + @td.skip_if_no_scipy |
| 263 | + @pytest.mark.parametrize('ascending', [True, False]) |
| 264 | + @pytest.mark.parametrize('method', ['average', 'min', 'max', 'first', |
| 265 | + 'dense']) |
| 266 | + @pytest.mark.parametrize('na_option', ['top', 'bottom', 'keep']) |
| 267 | + def test_rank_tie_methods_on_infs_nans(self, method, na_option, ascending): |
261 | 268 | dtypes = [('object', None, Infinity(), NegInfinity()),
|
262 | 269 | ('float64', np.nan, np.inf, -np.inf)]
|
263 | 270 | chunk = 3
|
264 | 271 | disabled = set([('object', 'first')])
|
265 | 272 |
|
266 |
| - def _check(s, expected, method='average', na_option='keep'): |
267 |
| - result = s.rank(method=method, na_option=na_option) |
| 273 | + def _check(s, method, na_option, ascending): |
| 274 | + exp_ranks = { |
| 275 | + 'average': ([2, 2, 2], [5, 5, 5], [8, 8, 8]), |
| 276 | + 'min': ([1, 1, 1], [4, 4, 4], [7, 7, 7]), |
| 277 | + 'max': ([3, 3, 3], [6, 6, 6], [9, 9, 9]), |
| 278 | + 'first': ([1, 2, 3], [4, 5, 6], [7, 8, 9]), |
| 279 | + 'dense': ([1, 1, 1], [2, 2, 2], [3, 3, 3]) |
| 280 | + } |
| 281 | + ranks = exp_ranks[method] |
| 282 | + if na_option == 'top': |
| 283 | + order = [ranks[1], ranks[0], ranks[2]] |
| 284 | + elif na_option == 'bottom': |
| 285 | + order = [ranks[0], ranks[2], ranks[1]] |
| 286 | + else: |
| 287 | + order = [ranks[0], [np.nan] * chunk, ranks[1]] |
| 288 | + expected = order if ascending else order[::-1] |
| 289 | + expected = list(chain.from_iterable(expected)) |
| 290 | + result = s.rank(method=method, na_option=na_option, |
| 291 | + ascending=ascending) |
268 | 292 | tm.assert_series_equal(result, Series(expected, dtype='float64'))
|
269 | 293 |
|
270 |
| - exp_ranks = { |
271 |
| - 'average': ([2, 2, 2], [5, 5, 5], [8, 8, 8]), |
272 |
| - 'min': ([1, 1, 1], [4, 4, 4], [7, 7, 7]), |
273 |
| - 'max': ([3, 3, 3], [6, 6, 6], [9, 9, 9]), |
274 |
| - 'first': ([1, 2, 3], [4, 5, 6], [7, 8, 9]), |
275 |
| - 'dense': ([1, 1, 1], [2, 2, 2], [3, 3, 3]) |
276 |
| - } |
277 |
| - na_options = ('top', 'bottom', 'keep') |
278 | 294 | for dtype, na_value, pos_inf, neg_inf in dtypes:
|
279 | 295 | in_arr = [neg_inf] * chunk + [na_value] * chunk + [pos_inf] * chunk
|
280 | 296 | iseries = Series(in_arr, dtype=dtype)
|
281 |
| - for method, na_opt in product(exp_ranks.keys(), na_options): |
282 |
| - ranks = exp_ranks[method] |
283 |
| - if (dtype, method) in disabled: |
284 |
| - continue |
285 |
| - if na_opt == 'top': |
286 |
| - order = ranks[1] + ranks[0] + ranks[2] |
287 |
| - elif na_opt == 'bottom': |
288 |
| - order = ranks[0] + ranks[2] + ranks[1] |
289 |
| - else: |
290 |
| - order = ranks[0] + [np.nan] * chunk + ranks[1] |
291 |
| - _check(iseries, order, method, na_opt) |
| 297 | + if (dtype, method) in disabled: |
| 298 | + continue |
| 299 | + _check(iseries, method, na_option, ascending) |
| 300 | + |
| 301 | + def test_rank_desc_mix_nans_infs(self): |
| 302 | + # GH 19538 |
| 303 | + # check descending ranking when mix nans and infs |
| 304 | + iseries = Series([1, np.nan, np.inf, -np.inf, 25]) |
| 305 | + result = iseries.rank(ascending=False) |
| 306 | + exp = Series([3, np.nan, 1, 4, 2], dtype='float64') |
| 307 | + tm.assert_series_equal(result, exp) |
292 | 308 |
|
293 | 309 | def test_rank_methods_series(self):
|
294 | 310 | pytest.importorskip('scipy.stats.special')
|
|
0 commit comments