test_rank.py 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506
  1. # -*- coding: utf-8 -*-
  2. from distutils.version import LooseVersion
  3. from itertools import chain
  4. import numpy as np
  5. from numpy import nan
  6. import pytest
  7. from pandas._libs.algos import Infinity, NegInfinity
  8. from pandas._libs.tslib import iNaT
  9. import pandas.compat as compat
  10. from pandas.compat import product
  11. import pandas.util._test_decorators as td
  12. from pandas import NaT, Series, Timestamp, date_range
  13. from pandas.api.types import CategoricalDtype
  14. from pandas.tests.series.common import TestData
  15. import pandas.util.testing as tm
  16. from pandas.util.testing import assert_series_equal
  17. class TestSeriesRank(TestData):
  18. s = Series([1, 3, 4, 2, nan, 2, 1, 5, nan, 3])
  19. results = {
  20. 'average': np.array([1.5, 5.5, 7.0, 3.5, nan,
  21. 3.5, 1.5, 8.0, nan, 5.5]),
  22. 'min': np.array([1, 5, 7, 3, nan, 3, 1, 8, nan, 5]),
  23. 'max': np.array([2, 6, 7, 4, nan, 4, 2, 8, nan, 6]),
  24. 'first': np.array([1, 5, 7, 3, nan, 4, 2, 8, nan, 6]),
  25. 'dense': np.array([1, 3, 4, 2, nan, 2, 1, 5, nan, 3]),
  26. }
  27. def test_rank(self):
  28. pytest.importorskip('scipy.stats.special')
  29. rankdata = pytest.importorskip('scipy.stats.rankdata')
  30. self.ts[::2] = np.nan
  31. self.ts[:10][::3] = 4.
  32. ranks = self.ts.rank()
  33. oranks = self.ts.astype('O').rank()
  34. assert_series_equal(ranks, oranks)
  35. mask = np.isnan(self.ts)
  36. filled = self.ts.fillna(np.inf)
  37. # rankdata returns a ndarray
  38. exp = Series(rankdata(filled), index=filled.index, name='ts')
  39. exp[mask] = np.nan
  40. tm.assert_series_equal(ranks, exp)
  41. iseries = Series(np.arange(5).repeat(2))
  42. iranks = iseries.rank()
  43. exp = iseries.astype(float).rank()
  44. assert_series_equal(iranks, exp)
  45. iseries = Series(np.arange(5)) + 1.0
  46. exp = iseries / 5.0
  47. iranks = iseries.rank(pct=True)
  48. assert_series_equal(iranks, exp)
  49. iseries = Series(np.repeat(1, 100))
  50. exp = Series(np.repeat(0.505, 100))
  51. iranks = iseries.rank(pct=True)
  52. assert_series_equal(iranks, exp)
  53. iseries[1] = np.nan
  54. exp = Series(np.repeat(50.0 / 99.0, 100))
  55. exp[1] = np.nan
  56. iranks = iseries.rank(pct=True)
  57. assert_series_equal(iranks, exp)
  58. iseries = Series(np.arange(5)) + 1.0
  59. iseries[4] = np.nan
  60. exp = iseries / 4.0
  61. iranks = iseries.rank(pct=True)
  62. assert_series_equal(iranks, exp)
  63. iseries = Series(np.repeat(np.nan, 100))
  64. exp = iseries.copy()
  65. iranks = iseries.rank(pct=True)
  66. assert_series_equal(iranks, exp)
  67. iseries = Series(np.arange(5)) + 1
  68. iseries[4] = np.nan
  69. exp = iseries / 4.0
  70. iranks = iseries.rank(pct=True)
  71. assert_series_equal(iranks, exp)
  72. rng = date_range('1/1/1990', periods=5)
  73. iseries = Series(np.arange(5), rng) + 1
  74. iseries.iloc[4] = np.nan
  75. exp = iseries / 4.0
  76. iranks = iseries.rank(pct=True)
  77. assert_series_equal(iranks, exp)
  78. iseries = Series([1e-50, 1e-100, 1e-20, 1e-2, 1e-20 + 1e-30, 1e-1])
  79. exp = Series([2, 1, 3, 5, 4, 6.0])
  80. iranks = iseries.rank()
  81. assert_series_equal(iranks, exp)
  82. # GH 5968
  83. iseries = Series(['3 day', '1 day 10m', '-2 day', NaT],
  84. dtype='m8[ns]')
  85. exp = Series([3, 2, 1, np.nan])
  86. iranks = iseries.rank()
  87. assert_series_equal(iranks, exp)
  88. values = np.array(
  89. [-50, -1, -1e-20, -1e-25, -1e-50, 0, 1e-40, 1e-20, 1e-10, 2, 40
  90. ], dtype='float64')
  91. random_order = np.random.permutation(len(values))
  92. iseries = Series(values[random_order])
  93. exp = Series(random_order + 1.0, dtype='float64')
  94. iranks = iseries.rank()
  95. assert_series_equal(iranks, exp)
  96. def test_rank_categorical(self):
  97. # GH issue #15420 rank incorrectly orders ordered categories
  98. # Test ascending/descending ranking for ordered categoricals
  99. exp = Series([1., 2., 3., 4., 5., 6.])
  100. exp_desc = Series([6., 5., 4., 3., 2., 1.])
  101. ordered = Series(
  102. ['first', 'second', 'third', 'fourth', 'fifth', 'sixth']
  103. ).astype(CategoricalDtype(categories=['first', 'second', 'third',
  104. 'fourth', 'fifth', 'sixth'],
  105. ordered=True))
  106. assert_series_equal(ordered.rank(), exp)
  107. assert_series_equal(ordered.rank(ascending=False), exp_desc)
  108. # Unordered categoricals should be ranked as objects
  109. unordered = Series(['first', 'second', 'third', 'fourth',
  110. 'fifth', 'sixth']).astype(
  111. CategoricalDtype(categories=['first', 'second', 'third',
  112. 'fourth', 'fifth', 'sixth'],
  113. ordered=False))
  114. exp_unordered = Series([2., 4., 6., 3., 1., 5.])
  115. res = unordered.rank()
  116. assert_series_equal(res, exp_unordered)
  117. unordered1 = Series(
  118. [1, 2, 3, 4, 5, 6],
  119. ).astype(CategoricalDtype([1, 2, 3, 4, 5, 6], False))
  120. exp_unordered1 = Series([1., 2., 3., 4., 5., 6.])
  121. res1 = unordered1.rank()
  122. assert_series_equal(res1, exp_unordered1)
  123. # Test na_option for rank data
  124. na_ser = Series(
  125. ['first', 'second', 'third', 'fourth', 'fifth', 'sixth', np.NaN]
  126. ).astype(CategoricalDtype(['first', 'second', 'third', 'fourth',
  127. 'fifth', 'sixth', 'seventh'], True))
  128. exp_top = Series([2., 3., 4., 5., 6., 7., 1.])
  129. exp_bot = Series([1., 2., 3., 4., 5., 6., 7.])
  130. exp_keep = Series([1., 2., 3., 4., 5., 6., np.NaN])
  131. assert_series_equal(na_ser.rank(na_option='top'), exp_top)
  132. assert_series_equal(na_ser.rank(na_option='bottom'), exp_bot)
  133. assert_series_equal(na_ser.rank(na_option='keep'), exp_keep)
  134. # Test na_option for rank data with ascending False
  135. exp_top = Series([7., 6., 5., 4., 3., 2., 1.])
  136. exp_bot = Series([6., 5., 4., 3., 2., 1., 7.])
  137. exp_keep = Series([6., 5., 4., 3., 2., 1., np.NaN])
  138. assert_series_equal(
  139. na_ser.rank(na_option='top', ascending=False),
  140. exp_top
  141. )
  142. assert_series_equal(
  143. na_ser.rank(na_option='bottom', ascending=False),
  144. exp_bot
  145. )
  146. assert_series_equal(
  147. na_ser.rank(na_option='keep', ascending=False),
  148. exp_keep
  149. )
  150. # Test invalid values for na_option
  151. msg = "na_option must be one of 'keep', 'top', or 'bottom'"
  152. with pytest.raises(ValueError, match=msg):
  153. na_ser.rank(na_option='bad', ascending=False)
  154. # invalid type
  155. with pytest.raises(ValueError, match=msg):
  156. na_ser.rank(na_option=True, ascending=False)
  157. # Test with pct=True
  158. na_ser = Series(['first', 'second', 'third', 'fourth', np.NaN]).astype(
  159. CategoricalDtype(['first', 'second', 'third', 'fourth'], True))
  160. exp_top = Series([0.4, 0.6, 0.8, 1., 0.2])
  161. exp_bot = Series([0.2, 0.4, 0.6, 0.8, 1.])
  162. exp_keep = Series([0.25, 0.5, 0.75, 1., np.NaN])
  163. assert_series_equal(na_ser.rank(na_option='top', pct=True), exp_top)
  164. assert_series_equal(na_ser.rank(na_option='bottom', pct=True), exp_bot)
  165. assert_series_equal(na_ser.rank(na_option='keep', pct=True), exp_keep)
  166. def test_rank_signature(self):
  167. s = Series([0, 1])
  168. s.rank(method='average')
  169. msg = r"No axis named average for object type <(class|type) 'type'>"
  170. with pytest.raises(ValueError, match=msg):
  171. s.rank('average')
  172. @pytest.mark.parametrize('contents,dtype', [
  173. ([-np.inf, -50, -1, -1e-20, -1e-25, -1e-50, 0, 1e-40, 1e-20, 1e-10,
  174. 2, 40, np.inf],
  175. 'float64'),
  176. ([-np.inf, -50, -1, -1e-20, -1e-25, -1e-45, 0, 1e-40, 1e-20, 1e-10,
  177. 2, 40, np.inf],
  178. 'float32'),
  179. ([np.iinfo(np.uint8).min, 1, 2, 100, np.iinfo(np.uint8).max],
  180. 'uint8'),
  181. pytest.param([np.iinfo(np.int64).min, -100, 0, 1, 9999, 100000,
  182. 1e10, np.iinfo(np.int64).max],
  183. 'int64',
  184. marks=pytest.mark.xfail(
  185. reason="iNaT is equivalent to minimum value of dtype"
  186. "int64 pending issue GH#16674")),
  187. ([NegInfinity(), '1', 'A', 'BA', 'Ba', 'C', Infinity()],
  188. 'object')
  189. ])
  190. def test_rank_inf(self, contents, dtype):
  191. dtype_na_map = {
  192. 'float64': np.nan,
  193. 'float32': np.nan,
  194. 'int64': iNaT,
  195. 'object': None
  196. }
  197. # Insert nans at random positions if underlying dtype has missing
  198. # value. Then adjust the expected order by adding nans accordingly
  199. # This is for testing whether rank calculation is affected
  200. # when values are interwined with nan values.
  201. values = np.array(contents, dtype=dtype)
  202. exp_order = np.array(range(len(values)), dtype='float64') + 1.0
  203. if dtype in dtype_na_map:
  204. na_value = dtype_na_map[dtype]
  205. nan_indices = np.random.choice(range(len(values)), 5)
  206. values = np.insert(values, nan_indices, na_value)
  207. exp_order = np.insert(exp_order, nan_indices, np.nan)
  208. # shuffle the testing array and expected results in the same way
  209. random_order = np.random.permutation(len(values))
  210. iseries = Series(values[random_order])
  211. exp = Series(exp_order[random_order], dtype='float64')
  212. iranks = iseries.rank()
  213. assert_series_equal(iranks, exp)
  214. def test_rank_tie_methods(self):
  215. s = self.s
  216. def _check(s, expected, method='average'):
  217. result = s.rank(method=method)
  218. tm.assert_series_equal(result, Series(expected))
  219. dtypes = [None, object]
  220. disabled = {(object, 'first')}
  221. results = self.results
  222. for method, dtype in product(results, dtypes):
  223. if (dtype, method) in disabled:
  224. continue
  225. series = s if dtype is None else s.astype(dtype)
  226. _check(series, results[method], method=method)
  227. @td.skip_if_no_scipy
  228. @pytest.mark.parametrize('ascending', [True, False])
  229. @pytest.mark.parametrize('method', ['average', 'min', 'max', 'first',
  230. 'dense'])
  231. @pytest.mark.parametrize('na_option', ['top', 'bottom', 'keep'])
  232. def test_rank_tie_methods_on_infs_nans(self, method, na_option, ascending):
  233. dtypes = [('object', None, Infinity(), NegInfinity()),
  234. ('float64', np.nan, np.inf, -np.inf)]
  235. chunk = 3
  236. disabled = {('object', 'first')}
  237. def _check(s, method, na_option, ascending):
  238. exp_ranks = {
  239. 'average': ([2, 2, 2], [5, 5, 5], [8, 8, 8]),
  240. 'min': ([1, 1, 1], [4, 4, 4], [7, 7, 7]),
  241. 'max': ([3, 3, 3], [6, 6, 6], [9, 9, 9]),
  242. 'first': ([1, 2, 3], [4, 5, 6], [7, 8, 9]),
  243. 'dense': ([1, 1, 1], [2, 2, 2], [3, 3, 3])
  244. }
  245. ranks = exp_ranks[method]
  246. if na_option == 'top':
  247. order = [ranks[1], ranks[0], ranks[2]]
  248. elif na_option == 'bottom':
  249. order = [ranks[0], ranks[2], ranks[1]]
  250. else:
  251. order = [ranks[0], [np.nan] * chunk, ranks[1]]
  252. expected = order if ascending else order[::-1]
  253. expected = list(chain.from_iterable(expected))
  254. result = s.rank(method=method, na_option=na_option,
  255. ascending=ascending)
  256. tm.assert_series_equal(result, Series(expected, dtype='float64'))
  257. for dtype, na_value, pos_inf, neg_inf in dtypes:
  258. in_arr = [neg_inf] * chunk + [na_value] * chunk + [pos_inf] * chunk
  259. iseries = Series(in_arr, dtype=dtype)
  260. if (dtype, method) in disabled:
  261. continue
  262. _check(iseries, method, na_option, ascending)
  263. def test_rank_desc_mix_nans_infs(self):
  264. # GH 19538
  265. # check descending ranking when mix nans and infs
  266. iseries = Series([1, np.nan, np.inf, -np.inf, 25])
  267. result = iseries.rank(ascending=False)
  268. exp = Series([3, np.nan, 1, 4, 2], dtype='float64')
  269. tm.assert_series_equal(result, exp)
  270. def test_rank_methods_series(self):
  271. pytest.importorskip('scipy.stats.special')
  272. rankdata = pytest.importorskip('scipy.stats.rankdata')
  273. import scipy
  274. xs = np.random.randn(9)
  275. xs = np.concatenate([xs[i:] for i in range(0, 9, 2)]) # add duplicates
  276. np.random.shuffle(xs)
  277. index = [chr(ord('a') + i) for i in range(len(xs))]
  278. for vals in [xs, xs + 1e6, xs * 1e-6]:
  279. ts = Series(vals, index=index)
  280. for m in ['average', 'min', 'max', 'first', 'dense']:
  281. result = ts.rank(method=m)
  282. sprank = rankdata(vals, m if m != 'first' else 'ordinal')
  283. expected = Series(sprank, index=index)
  284. if LooseVersion(scipy.__version__) >= LooseVersion('0.17.0'):
  285. expected = expected.astype('float64')
  286. tm.assert_series_equal(result, expected)
  287. def test_rank_dense_method(self):
  288. dtypes = ['O', 'f8', 'i8']
  289. in_out = [([1], [1]),
  290. ([2], [1]),
  291. ([0], [1]),
  292. ([2, 2], [1, 1]),
  293. ([1, 2, 3], [1, 2, 3]),
  294. ([4, 2, 1], [3, 2, 1],),
  295. ([1, 1, 5, 5, 3], [1, 1, 3, 3, 2]),
  296. ([-5, -4, -3, -2, -1], [1, 2, 3, 4, 5])]
  297. for ser, exp in in_out:
  298. for dtype in dtypes:
  299. s = Series(ser).astype(dtype)
  300. result = s.rank(method='dense')
  301. expected = Series(exp).astype(result.dtype)
  302. assert_series_equal(result, expected)
  303. def test_rank_descending(self):
  304. dtypes = ['O', 'f8', 'i8']
  305. for dtype, method in product(dtypes, self.results):
  306. if 'i' in dtype:
  307. s = self.s.dropna()
  308. else:
  309. s = self.s.astype(dtype)
  310. res = s.rank(ascending=False)
  311. expected = (s.max() - s).rank()
  312. assert_series_equal(res, expected)
  313. if method == 'first' and dtype == 'O':
  314. continue
  315. expected = (s.max() - s).rank(method=method)
  316. res2 = s.rank(method=method, ascending=False)
  317. assert_series_equal(res2, expected)
  318. def test_rank_int(self):
  319. s = self.s.dropna().astype('i8')
  320. for method, res in compat.iteritems(self.results):
  321. result = s.rank(method=method)
  322. expected = Series(res).dropna()
  323. expected.index = result.index
  324. assert_series_equal(result, expected)
  325. def test_rank_object_bug(self):
  326. # GH 13445
  327. # smoke tests
  328. Series([np.nan] * 32).astype(object).rank(ascending=True)
  329. Series([np.nan] * 32).astype(object).rank(ascending=False)
  330. def test_rank_modify_inplace(self):
  331. # GH 18521
  332. # Check rank does not mutate series
  333. s = Series([Timestamp('2017-01-05 10:20:27.569000'), NaT])
  334. expected = s.copy()
  335. s.rank()
  336. result = s
  337. assert_series_equal(result, expected)
  338. # GH15630, pct should be on 100% basis when method='dense'
  339. @pytest.mark.parametrize('dtype', ['O', 'f8', 'i8'])
  340. @pytest.mark.parametrize('ser, exp', [
  341. ([1], [1.]),
  342. ([1, 2], [1. / 2, 2. / 2]),
  343. ([2, 2], [1., 1.]),
  344. ([1, 2, 3], [1. / 3, 2. / 3, 3. / 3]),
  345. ([1, 2, 2], [1. / 2, 2. / 2, 2. / 2]),
  346. ([4, 2, 1], [3. / 3, 2. / 3, 1. / 3],),
  347. ([1, 1, 5, 5, 3], [1. / 3, 1. / 3, 3. / 3, 3. / 3, 2. / 3]),
  348. ([1, 1, 3, 3, 5, 5], [1. / 3, 1. / 3, 2. / 3, 2. / 3, 3. / 3, 3. / 3]),
  349. ([-5, -4, -3, -2, -1], [1. / 5, 2. / 5, 3. / 5, 4. / 5, 5. / 5])])
  350. def test_rank_dense_pct(dtype, ser, exp):
  351. s = Series(ser).astype(dtype)
  352. result = s.rank(method='dense', pct=True)
  353. expected = Series(exp).astype(result.dtype)
  354. assert_series_equal(result, expected)
  355. @pytest.mark.parametrize('dtype', ['O', 'f8', 'i8'])
  356. @pytest.mark.parametrize('ser, exp', [
  357. ([1], [1.]),
  358. ([1, 2], [1. / 2, 2. / 2]),
  359. ([2, 2], [1. / 2, 1. / 2]),
  360. ([1, 2, 3], [1. / 3, 2. / 3, 3. / 3]),
  361. ([1, 2, 2], [1. / 3, 2. / 3, 2. / 3]),
  362. ([4, 2, 1], [3. / 3, 2. / 3, 1. / 3],),
  363. ([1, 1, 5, 5, 3], [1. / 5, 1. / 5, 4. / 5, 4. / 5, 3. / 5]),
  364. ([1, 1, 3, 3, 5, 5], [1. / 6, 1. / 6, 3. / 6, 3. / 6, 5. / 6, 5. / 6]),
  365. ([-5, -4, -3, -2, -1], [1. / 5, 2. / 5, 3. / 5, 4. / 5, 5. / 5])])
  366. def test_rank_min_pct(dtype, ser, exp):
  367. s = Series(ser).astype(dtype)
  368. result = s.rank(method='min', pct=True)
  369. expected = Series(exp).astype(result.dtype)
  370. assert_series_equal(result, expected)
  371. @pytest.mark.parametrize('dtype', ['O', 'f8', 'i8'])
  372. @pytest.mark.parametrize('ser, exp', [
  373. ([1], [1.]),
  374. ([1, 2], [1. / 2, 2. / 2]),
  375. ([2, 2], [1., 1.]),
  376. ([1, 2, 3], [1. / 3, 2. / 3, 3. / 3]),
  377. ([1, 2, 2], [1. / 3, 3. / 3, 3. / 3]),
  378. ([4, 2, 1], [3. / 3, 2. / 3, 1. / 3],),
  379. ([1, 1, 5, 5, 3], [2. / 5, 2. / 5, 5. / 5, 5. / 5, 3. / 5]),
  380. ([1, 1, 3, 3, 5, 5], [2. / 6, 2. / 6, 4. / 6, 4. / 6, 6. / 6, 6. / 6]),
  381. ([-5, -4, -3, -2, -1], [1. / 5, 2. / 5, 3. / 5, 4. / 5, 5. / 5])])
  382. def test_rank_max_pct(dtype, ser, exp):
  383. s = Series(ser).astype(dtype)
  384. result = s.rank(method='max', pct=True)
  385. expected = Series(exp).astype(result.dtype)
  386. assert_series_equal(result, expected)
  387. @pytest.mark.parametrize('dtype', ['O', 'f8', 'i8'])
  388. @pytest.mark.parametrize('ser, exp', [
  389. ([1], [1.]),
  390. ([1, 2], [1. / 2, 2. / 2]),
  391. ([2, 2], [1.5 / 2, 1.5 / 2]),
  392. ([1, 2, 3], [1. / 3, 2. / 3, 3. / 3]),
  393. ([1, 2, 2], [1. / 3, 2.5 / 3, 2.5 / 3]),
  394. ([4, 2, 1], [3. / 3, 2. / 3, 1. / 3],),
  395. ([1, 1, 5, 5, 3], [1.5 / 5, 1.5 / 5, 4.5 / 5, 4.5 / 5, 3. / 5]),
  396. ([1, 1, 3, 3, 5, 5],
  397. [1.5 / 6, 1.5 / 6, 3.5 / 6, 3.5 / 6, 5.5 / 6, 5.5 / 6]),
  398. ([-5, -4, -3, -2, -1], [1. / 5, 2. / 5, 3. / 5, 4. / 5, 5. / 5])])
  399. def test_rank_average_pct(dtype, ser, exp):
  400. s = Series(ser).astype(dtype)
  401. result = s.rank(method='average', pct=True)
  402. expected = Series(exp).astype(result.dtype)
  403. assert_series_equal(result, expected)
  404. @pytest.mark.parametrize('dtype', ['f8', 'i8'])
  405. @pytest.mark.parametrize('ser, exp', [
  406. ([1], [1.]),
  407. ([1, 2], [1. / 2, 2. / 2]),
  408. ([2, 2], [1. / 2, 2. / 2.]),
  409. ([1, 2, 3], [1. / 3, 2. / 3, 3. / 3]),
  410. ([1, 2, 2], [1. / 3, 2. / 3, 3. / 3]),
  411. ([4, 2, 1], [3. / 3, 2. / 3, 1. / 3],),
  412. ([1, 1, 5, 5, 3], [1. / 5, 2. / 5, 4. / 5, 5. / 5, 3. / 5]),
  413. ([1, 1, 3, 3, 5, 5], [1. / 6, 2. / 6, 3. / 6, 4. / 6, 5. / 6, 6. / 6]),
  414. ([-5, -4, -3, -2, -1], [1. / 5, 2. / 5, 3. / 5, 4. / 5, 5. / 5])])
  415. def test_rank_first_pct(dtype, ser, exp):
  416. s = Series(ser).astype(dtype)
  417. result = s.rank(method='first', pct=True)
  418. expected = Series(exp).astype(result.dtype)
  419. assert_series_equal(result, expected)
  420. @pytest.mark.single
  421. def test_pct_max_many_rows():
  422. # GH 18271
  423. s = Series(np.arange(2**24 + 1))
  424. result = s.rank(pct=True).max()
  425. assert result == 1