1
1
import numpy as np
2
2
import pytest
3
3
4
- from pandas import Float64Index , Index , Int64Index , Series , UInt64Index
4
+ from pandas import Float64Index , Index , Int64Index , RangeIndex , Series , UInt64Index
5
5
import pandas ._testing as tm
6
6
7
7
@@ -13,6 +13,54 @@ def index_large():
13
13
14
14
15
15
class TestGetLoc :
16
+ @pytest .mark .parametrize ("method" , [None , "pad" , "backfill" , "nearest" ])
17
+ def test_get_loc (self , method ):
18
+ index = Index ([0 , 1 , 2 ])
19
+ assert index .get_loc (1 , method = method ) == 1
20
+
21
+ if method :
22
+ assert index .get_loc (1 , method = method , tolerance = 0 ) == 1
23
+
24
+ @pytest .mark .parametrize ("method" , [None , "pad" , "backfill" , "nearest" ])
25
+ def test_get_loc_raises_bad_label (self , method ):
26
+ index = Index ([0 , 1 , 2 ])
27
+ if method :
28
+ msg = "not supported between"
29
+ else :
30
+ msg = "invalid key"
31
+
32
+ with pytest .raises (TypeError , match = msg ):
33
+ index .get_loc ([1 , 2 ], method = method )
34
+
35
+ @pytest .mark .parametrize (
36
+ "method,loc" , [("pad" , 1 ), ("backfill" , 2 ), ("nearest" , 1 )]
37
+ )
38
+ def test_get_loc_tolerance (self , method , loc ):
39
+ index = Index ([0 , 1 , 2 ])
40
+ assert index .get_loc (1.1 , method ) == loc
41
+ assert index .get_loc (1.1 , method , tolerance = 1 ) == loc
42
+
43
+ @pytest .mark .parametrize ("method" , ["pad" , "backfill" , "nearest" ])
44
+ def test_get_loc_outside_tolerance_raises (self , method ):
45
+ index = Index ([0 , 1 , 2 ])
46
+ with pytest .raises (KeyError , match = "1.1" ):
47
+ index .get_loc (1.1 , method , tolerance = 0.05 )
48
+
49
+ def test_get_loc_bad_tolerance_raises (self ):
50
+ index = Index ([0 , 1 , 2 ])
51
+ with pytest .raises (ValueError , match = "must be numeric" ):
52
+ index .get_loc (1.1 , "nearest" , tolerance = "invalid" )
53
+
54
+ def test_get_loc_tolerance_no_method_raises (self ):
55
+ index = Index ([0 , 1 , 2 ])
56
+ with pytest .raises (ValueError , match = "tolerance .* valid if" ):
57
+ index .get_loc (1.1 , tolerance = 1 )
58
+
59
+ def test_get_loc_raises_missized_tolerance (self ):
60
+ index = Index ([0 , 1 , 2 ])
61
+ with pytest .raises (ValueError , match = "tolerance size must match" ):
62
+ index .get_loc (1.1 , "nearest" , tolerance = [1 , 1 ])
63
+
16
64
def test_get_loc_float64 (self ):
17
65
idx = Float64Index ([0.0 , 1.0 , 2.0 ])
18
66
for method in [None , "pad" , "backfill" , "nearest" ]:
@@ -82,6 +130,131 @@ def test_get_loc_missing_nan(self):
82
130
83
131
84
132
class TestGetIndexer :
133
+ def test_get_indexer (self ):
134
+ index1 = Index ([1 , 2 , 3 , 4 , 5 ])
135
+ index2 = Index ([2 , 4 , 6 ])
136
+
137
+ r1 = index1 .get_indexer (index2 )
138
+ e1 = np .array ([1 , 3 , - 1 ], dtype = np .intp )
139
+ tm .assert_almost_equal (r1 , e1 )
140
+
141
+ @pytest .mark .parametrize ("reverse" , [True , False ])
142
+ @pytest .mark .parametrize (
143
+ "expected,method" ,
144
+ [
145
+ (np .array ([- 1 , 0 , 0 , 1 , 1 ], dtype = np .intp ), "pad" ),
146
+ (np .array ([- 1 , 0 , 0 , 1 , 1 ], dtype = np .intp ), "ffill" ),
147
+ (np .array ([0 , 0 , 1 , 1 , 2 ], dtype = np .intp ), "backfill" ),
148
+ (np .array ([0 , 0 , 1 , 1 , 2 ], dtype = np .intp ), "bfill" ),
149
+ ],
150
+ )
151
+ def test_get_indexer_methods (self , reverse , expected , method ):
152
+ index1 = Index ([1 , 2 , 3 , 4 , 5 ])
153
+ index2 = Index ([2 , 4 , 6 ])
154
+
155
+ if reverse :
156
+ index1 = index1 [::- 1 ]
157
+ expected = expected [::- 1 ]
158
+
159
+ result = index2 .get_indexer (index1 , method = method )
160
+ tm .assert_almost_equal (result , expected )
161
+
162
+ def test_get_indexer_invalid (self ):
163
+ # GH10411
164
+ index = Index (np .arange (10 ))
165
+
166
+ with pytest .raises (ValueError , match = "tolerance argument" ):
167
+ index .get_indexer ([1 , 0 ], tolerance = 1 )
168
+
169
+ with pytest .raises (ValueError , match = "limit argument" ):
170
+ index .get_indexer ([1 , 0 ], limit = 1 )
171
+
172
+ @pytest .mark .parametrize (
173
+ "method, tolerance, indexer, expected" ,
174
+ [
175
+ ("pad" , None , [0 , 5 , 9 ], [0 , 5 , 9 ]),
176
+ ("backfill" , None , [0 , 5 , 9 ], [0 , 5 , 9 ]),
177
+ ("nearest" , None , [0 , 5 , 9 ], [0 , 5 , 9 ]),
178
+ ("pad" , 0 , [0 , 5 , 9 ], [0 , 5 , 9 ]),
179
+ ("backfill" , 0 , [0 , 5 , 9 ], [0 , 5 , 9 ]),
180
+ ("nearest" , 0 , [0 , 5 , 9 ], [0 , 5 , 9 ]),
181
+ ("pad" , None , [0.2 , 1.8 , 8.5 ], [0 , 1 , 8 ]),
182
+ ("backfill" , None , [0.2 , 1.8 , 8.5 ], [1 , 2 , 9 ]),
183
+ ("nearest" , None , [0.2 , 1.8 , 8.5 ], [0 , 2 , 9 ]),
184
+ ("pad" , 1 , [0.2 , 1.8 , 8.5 ], [0 , 1 , 8 ]),
185
+ ("backfill" , 1 , [0.2 , 1.8 , 8.5 ], [1 , 2 , 9 ]),
186
+ ("nearest" , 1 , [0.2 , 1.8 , 8.5 ], [0 , 2 , 9 ]),
187
+ ("pad" , 0.2 , [0.2 , 1.8 , 8.5 ], [0 , - 1 , - 1 ]),
188
+ ("backfill" , 0.2 , [0.2 , 1.8 , 8.5 ], [- 1 , 2 , - 1 ]),
189
+ ("nearest" , 0.2 , [0.2 , 1.8 , 8.5 ], [0 , 2 , - 1 ]),
190
+ ],
191
+ )
192
+ def test_get_indexer_nearest (self , method , tolerance , indexer , expected ):
193
+ index = Index (np .arange (10 ))
194
+
195
+ actual = index .get_indexer (indexer , method = method , tolerance = tolerance )
196
+ tm .assert_numpy_array_equal (actual , np .array (expected , dtype = np .intp ))
197
+
198
+ @pytest .mark .parametrize ("listtype" , [list , tuple , Series , np .array ])
199
+ @pytest .mark .parametrize (
200
+ "tolerance, expected" ,
201
+ list (
202
+ zip (
203
+ [[0.3 , 0.3 , 0.1 ], [0.2 , 0.1 , 0.1 ], [0.1 , 0.5 , 0.5 ]],
204
+ [[0 , 2 , - 1 ], [0 , - 1 , - 1 ], [- 1 , 2 , 9 ]],
205
+ )
206
+ ),
207
+ )
208
+ def test_get_indexer_nearest_listlike_tolerance (
209
+ self , tolerance , expected , listtype
210
+ ):
211
+ index = Index (np .arange (10 ))
212
+
213
+ actual = index .get_indexer (
214
+ [0.2 , 1.8 , 8.5 ], method = "nearest" , tolerance = listtype (tolerance )
215
+ )
216
+ tm .assert_numpy_array_equal (actual , np .array (expected , dtype = np .intp ))
217
+
218
+ def test_get_indexer_nearest_error (self ):
219
+ index = Index (np .arange (10 ))
220
+ with pytest .raises (ValueError , match = "limit argument" ):
221
+ index .get_indexer ([1 , 0 ], method = "nearest" , limit = 1 )
222
+
223
+ with pytest .raises (ValueError , match = "tolerance size must match" ):
224
+ index .get_indexer ([1 , 0 ], method = "nearest" , tolerance = [1 , 2 , 3 ])
225
+
226
+ @pytest .mark .parametrize (
227
+ "method,expected" ,
228
+ [("pad" , [8 , 7 , 0 ]), ("backfill" , [9 , 8 , 1 ]), ("nearest" , [9 , 7 , 0 ])],
229
+ )
230
+ def test_get_indexer_nearest_decreasing (self , method , expected ):
231
+ index = Index (np .arange (10 ))[::- 1 ]
232
+
233
+ actual = index .get_indexer ([0 , 5 , 9 ], method = method )
234
+ tm .assert_numpy_array_equal (actual , np .array ([9 , 4 , 0 ], dtype = np .intp ))
235
+
236
+ actual = index .get_indexer ([0.2 , 1.8 , 8.5 ], method = method )
237
+ tm .assert_numpy_array_equal (actual , np .array (expected , dtype = np .intp ))
238
+
239
+ @pytest .mark .parametrize (
240
+ "idx_class" , [Int64Index , RangeIndex , Float64Index , UInt64Index ]
241
+ )
242
+ @pytest .mark .parametrize ("method" , ["get_indexer" , "get_indexer_non_unique" ])
243
+ def test_get_indexer_numeric_index_boolean_target (self , method , idx_class ):
244
+ # GH 16877
245
+
246
+ numeric_index = idx_class (RangeIndex (4 ))
247
+ other = Index ([True , False , True ])
248
+
249
+ result = getattr (numeric_index , method )(other )
250
+ expected = np .array ([- 1 , - 1 , - 1 ], dtype = np .intp )
251
+ if method == "get_indexer" :
252
+ tm .assert_numpy_array_equal (result , expected )
253
+ else :
254
+ missing = np .arange (3 , dtype = np .intp )
255
+ tm .assert_numpy_array_equal (result [0 ], expected )
256
+ tm .assert_numpy_array_equal (result [1 ], missing )
257
+
85
258
@pytest .mark .parametrize ("method" , ["pad" , "backfill" , "nearest" ])
86
259
def test_get_indexer_with_method_numeric_vs_bool (self , method ):
87
260
left = Index ([1 , 2 , 3 ])
@@ -274,6 +447,62 @@ def test_contains_float64_not_nans(self):
274
447
assert 1.0 in index
275
448
276
449
450
+ class TestSliceLocs :
451
+ @pytest .mark .parametrize ("dtype" , [int , float ])
452
+ def test_slice_locs (self , dtype ):
453
+ index = Index (np .array ([0 , 1 , 2 , 5 , 6 , 7 , 9 , 10 ], dtype = dtype ))
454
+ n = len (index )
455
+
456
+ assert index .slice_locs (start = 2 ) == (2 , n )
457
+ assert index .slice_locs (start = 3 ) == (3 , n )
458
+ assert index .slice_locs (3 , 8 ) == (3 , 6 )
459
+ assert index .slice_locs (5 , 10 ) == (3 , n )
460
+ assert index .slice_locs (end = 8 ) == (0 , 6 )
461
+ assert index .slice_locs (end = 9 ) == (0 , 7 )
462
+
463
+ # reversed
464
+ index2 = index [::- 1 ]
465
+ assert index2 .slice_locs (8 , 2 ) == (2 , 6 )
466
+ assert index2 .slice_locs (7 , 3 ) == (2 , 5 )
467
+
468
+ @pytest .mark .parametrize ("dtype" , [int , float ])
469
+ def test_slice_locs_float_locs (self , dtype ):
470
+ index = Index (np .array ([0 , 1 , 2 , 5 , 6 , 7 , 9 , 10 ], dtype = dtype ))
471
+ n = len (index )
472
+ assert index .slice_locs (5.0 , 10.0 ) == (3 , n )
473
+ assert index .slice_locs (4.5 , 10.5 ) == (3 , 8 )
474
+
475
+ index2 = index [::- 1 ]
476
+ assert index2 .slice_locs (8.5 , 1.5 ) == (2 , 6 )
477
+ assert index2 .slice_locs (10.5 , - 1 ) == (0 , n )
478
+
479
+ @pytest .mark .parametrize ("dtype" , [int , float ])
480
+ def test_slice_locs_dup_numeric (self , dtype ):
481
+ index = Index (np .array ([10 , 12 , 12 , 14 ], dtype = dtype ))
482
+ assert index .slice_locs (12 , 12 ) == (1 , 3 )
483
+ assert index .slice_locs (11 , 13 ) == (1 , 3 )
484
+
485
+ index2 = index [::- 1 ]
486
+ assert index2 .slice_locs (12 , 12 ) == (1 , 3 )
487
+ assert index2 .slice_locs (13 , 11 ) == (1 , 3 )
488
+
489
+ def test_slice_locs_na (self ):
490
+ index = Index ([np .nan , 1 , 2 ])
491
+ assert index .slice_locs (1 ) == (1 , 3 )
492
+ assert index .slice_locs (np .nan ) == (0 , 3 )
493
+
494
+ index = Index ([0 , np .nan , np .nan , 1 , 2 ])
495
+ assert index .slice_locs (np .nan ) == (1 , 5 )
496
+
497
+ def test_slice_locs_na_raises (self ):
498
+ index = Index ([np .nan , 1 , 2 ])
499
+ with pytest .raises (KeyError , match = "" ):
500
+ index .slice_locs (start = 1.5 )
501
+
502
+ with pytest .raises (KeyError , match = "" ):
503
+ index .slice_locs (end = 1.5 )
504
+
505
+
277
506
class TestGetSliceBounds :
278
507
@pytest .mark .parametrize ("kind" , ["getitem" , "loc" , None ])
279
508
@pytest .mark .parametrize ("side, expected" , [("left" , 4 ), ("right" , 5 )])
0 commit comments