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