Skip to content

Commit f3ad606

Browse files
committed
add tests for engines and add is_monotonic_uint(32|16)
1 parent f7b3487 commit f3ad606

File tree

4 files changed

+150
-4
lines changed

4 files changed

+150
-4
lines changed

asv_bench/benchmarks/indexing_engines.py

+5-4
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import numpy as np
22

3-
from pandas._libs import index as li
3+
from pandas._libs import index as libindex
44

55

66
def _get_numeric_engines():
@@ -11,8 +11,9 @@ def _get_numeric_engines():
1111
('UInt16engine', np.uint16), ('UInt8Engine', np.uint8),
1212
('Float64Engine', np.float64), ('Float32Engine', np.float32),
1313
]
14-
return [(getattr(li, engine_name), dtype)
15-
for engine_name, dtype in engine_names if hasattr(li, engine_name)]
14+
return [(getattr(libindex, engine_name), dtype)
15+
for engine_name, dtype in engine_names
16+
if hasattr(libindex, engine_name)]
1617

1718

1819
class NumericEngineIndexing(object):
@@ -58,7 +59,7 @@ def setup(self, index_type):
5859
'non_monotonic': np.array(list('abc') * N, dtype=object),
5960
}[index_type]
6061

61-
self.data = li.ObjectEngine(lambda: arr, len(arr))
62+
self.data = libindex.ObjectEngine(lambda: arr, len(arr))
6263
# code belows avoids populating the mapping etc. while timing.
6364
self.data.get_loc('b')
6465

pandas/_libs/algos.pyx

+5
Original file line numberDiff line numberDiff line change
@@ -365,6 +365,8 @@ ctypedef fused algos_t:
365365
int16_t
366366
int8_t
367367
uint64_t
368+
uint32_t
369+
uint16_t
368370
uint8_t
369371

370372

@@ -872,6 +874,9 @@ is_monotonic_int32 = is_monotonic["int32_t"]
872874
is_monotonic_int16 = is_monotonic["int16_t"]
873875
is_monotonic_int8 = is_monotonic["int8_t"]
874876
is_monotonic_uint64 = is_monotonic["uint64_t"]
877+
is_monotonic_uint32 = is_monotonic["uint32_t"]
878+
is_monotonic_uint16 = is_monotonic["uint16_t"]
879+
is_monotonic_uint8 = is_monotonic["uint8_t"]
875880
is_monotonic_bool = is_monotonic["uint8_t"]
876881

877882

pandas/tests/indexing/conftest.py

+20
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
import numpy as np
2+
import pytest
3+
4+
from pandas._libs import index as libindex
5+
6+
7+
@pytest.fixture(params=[
8+
(libindex.Int64Engine, np.int64),
9+
(libindex.Int32Engine, np.int32),
10+
(libindex.Int16Engine, np.int16),
11+
(libindex.Int8Engine, np.int8),
12+
(libindex.UInt64Engine, np.uint64),
13+
(libindex.UInt32Engine, np.uint32),
14+
(libindex.UInt16Engine, np.uint16),
15+
(libindex.UInt8Engine, np.uint8),
16+
(libindex.Float64Engine, np.float64),
17+
(libindex.Float32Engine, np.float32),
18+
], ids=lambda x: x[0].__name__)
19+
def numeric_indexing_engine_type_and_dtype(request):
20+
return request.param
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
1+
import numpy as np
2+
3+
from pandas._libs import index as libindex
4+
5+
6+
class TestNumericEngine(object):
7+
def test_is_monotonic(self, numeric_indexing_engine_type_and_dtype):
8+
engine_type, dtype = numeric_indexing_engine_type_and_dtype
9+
10+
num = 1000
11+
arr = np.array([1] * num + [2] * num + [3] * num, dtype=dtype)
12+
13+
# monotonic increasing
14+
engine = engine_type(lambda: arr, len(arr))
15+
assert engine.is_monotonic_increasing
16+
assert not engine.is_monotonic_decreasing
17+
18+
# monotonic decreasing
19+
engine = engine_type(lambda: arr[::-1], len(arr))
20+
assert not engine.is_monotonic_increasing
21+
assert engine.is_monotonic_decreasing
22+
23+
# neither monotonic increasing or decreasing
24+
arr = np.array([1] * num + [2] * num + [1] * num, dtype=dtype)
25+
engine = engine_type(lambda: arr[::-1], len(arr))
26+
assert not engine.is_monotonic_increasing
27+
assert not engine.is_monotonic_decreasing
28+
29+
def test_is_unique(self, numeric_indexing_engine_type_and_dtype):
30+
engine_type, dtype = numeric_indexing_engine_type_and_dtype
31+
32+
# unique
33+
arr = np.array([1, 2, 4, 3], dtype=dtype)
34+
engine = engine_type(lambda: arr, len(arr))
35+
assert engine.is_unique
36+
37+
# not unique
38+
arr = np.array([1, 2, 1], dtype=dtype)
39+
engine = engine_type(lambda: arr, len(arr))
40+
assert not engine.is_unique
41+
42+
def test_get_loc(self, numeric_indexing_engine_type_and_dtype):
43+
engine_type, dtype = numeric_indexing_engine_type_and_dtype
44+
45+
# unique
46+
arr = np.array([1, 2, 3], dtype=dtype)
47+
engine = engine_type(lambda: arr, len(arr))
48+
assert engine.get_loc(2) == 1
49+
50+
# monotonic
51+
num = 1000
52+
arr = np.array([1] * num + [2] * num + [3] * num, dtype=dtype)
53+
engine = engine_type(lambda: arr, len(arr))
54+
assert engine.get_loc(2) == slice(1000, 2000)
55+
56+
# not monotonic
57+
arr = np.array([1, 2, 3] * num, dtype=dtype)
58+
engine = engine_type(lambda: arr, len(arr))
59+
expected = np.array([False, True, False] * num, dtype=bool)
60+
result = engine.get_loc(2)
61+
assert (result == expected).all()
62+
63+
64+
class TestObjectEngine(object):
65+
engine_type = libindex.ObjectEngine
66+
dtype = np.object_
67+
68+
def test_is_monotonic(self):
69+
70+
num = 1000
71+
arr = np.array(['a'] * num + ['a'] * num + ['c'] * num,
72+
dtype=self.dtype)
73+
74+
# monotonic increasing
75+
engine = self.engine_type(lambda: arr, len(arr))
76+
assert engine.is_monotonic_increasing
77+
assert not engine.is_monotonic_decreasing
78+
79+
# monotonic decreasing
80+
engine = self.engine_type(lambda: arr[::-1], len(arr))
81+
assert not engine.is_monotonic_increasing
82+
assert engine.is_monotonic_decreasing
83+
84+
# neither monotonic increasing or decreasing
85+
arr = np.array(['a'] * num + ['b'] * num + ['a'] * num,
86+
dtype=self.dtype)
87+
engine = self.engine_type(lambda: arr[::-1], len(arr))
88+
assert not engine.is_monotonic_increasing
89+
assert not engine.is_monotonic_decreasing
90+
91+
def test_is_unique(self):
92+
# unique
93+
arr = np.array(['a', 'b', 'c', 'd'], dtype=self.dtype)
94+
engine = self.engine_type(lambda: arr, len(arr))
95+
assert engine.is_unique
96+
97+
# not unique
98+
arr = np.array(['a', 'b', 'a'], dtype=self.dtype)
99+
engine = self.engine_type(lambda: arr, len(arr))
100+
assert not engine.is_unique
101+
102+
def test_get_loc(self):
103+
# unique
104+
arr = np.array(['a', 'b', 'c'], dtype=self.dtype)
105+
engine = self.engine_type(lambda: arr, len(arr))
106+
assert engine.get_loc('b') == 1
107+
108+
# monotonic
109+
num = 1000
110+
arr = np.array(['a'] * num + ['b'] * num + ['c'] * num,
111+
dtype=self.dtype)
112+
engine = self.engine_type(lambda: arr, len(arr))
113+
assert engine.get_loc('b') == slice(1000, 2000)
114+
115+
# not monotonic
116+
arr = np.array(['a', 'b', 'c'] * num, dtype=self.dtype)
117+
engine = self.engine_type(lambda: arr, len(arr))
118+
expected = np.array([False, True, False] * num, dtype=bool)
119+
result = engine.get_loc('b')
120+
assert (result == expected).all()

0 commit comments

Comments
 (0)