@@ -55,7 +55,7 @@ class NumericIndex(Index):
55
55
"""
56
56
57
57
_values : np .ndarray
58
- _default_dtype : np .dtype
58
+ _default_dtype : np .dtype | None = None
59
59
_dtype_validation_metadata : tuple [Callable [..., bool ], str ]
60
60
61
61
_is_numeric_dtype = True
@@ -88,7 +88,10 @@ def _ensure_array(cls, data, dtype, copy: bool):
88
88
if issubclass (data .dtype .type , str ):
89
89
cls ._string_data_error (data )
90
90
91
- if copy or not is_dtype_equal (data .dtype , cls ._default_dtype ):
91
+ if copy or (
92
+ cls ._default_dtype is not None
93
+ and not is_dtype_equal (data .dtype , cls ._default_dtype )
94
+ ):
92
95
subarr = np .array (data , dtype = cls ._default_dtype , copy = copy )
93
96
cls ._assert_safe_casting (data , subarr )
94
97
else :
@@ -202,173 +205,6 @@ def _is_all_dates(self) -> bool:
202
205
An Index instance can **only** contain hashable objects.
203
206
"""
204
207
205
- _int64_descr_args = {
206
- "klass" : "Int64Index" ,
207
- "ltype" : "integer" ,
208
- "dtype" : "int64" ,
209
- "extra" : "" ,
210
- }
211
-
212
-
213
- class IntegerIndex (NumericIndex ):
214
- """
215
- This is an abstract class for Int64Index, UInt64Index.
216
- """
217
-
218
- _default_dtype : np .dtype
219
- _can_hold_na = False
220
-
221
- @classmethod
222
- def _assert_safe_casting (cls , data , subarr ):
223
- """
224
- Ensure incoming data can be represented with matching signed-ness.
225
- """
226
- if data .dtype .kind != cls ._default_dtype .kind :
227
- if not np .array_equal (data , subarr ):
228
- raise TypeError ("Unsafe NumPy casting, you must explicitly cast" )
229
-
230
- def __contains__ (self , key ) -> bool :
231
- """
232
- Check if key is a float and has a decimal. If it has, return False.
233
- """
234
- hash (key )
235
- try :
236
- if is_float (key ) and int (key ) != key :
237
- # otherwise the `key in self._engine` check casts e.g. 1.1 -> 1
238
- return False
239
- return key in self ._engine
240
- except (OverflowError , TypeError , ValueError ):
241
- return False
242
-
243
- @property
244
- def inferred_type (self ) -> str :
245
- """
246
- Always 'integer' for ``Int64Index`` and ``UInt64Index``
247
- """
248
- return "integer"
249
-
250
- @property
251
- def asi8 (self ) -> np .ndarray :
252
- # do not cache or you'll create a memory leak
253
- warnings .warn (
254
- "Index.asi8 is deprecated and will be removed in a future version" ,
255
- FutureWarning ,
256
- stacklevel = 2 ,
257
- )
258
- return self ._values .view (self ._default_dtype )
259
-
260
-
261
- class Int64Index (IntegerIndex ):
262
- __doc__ = _num_index_shared_docs ["class_descr" ] % _int64_descr_args
263
-
264
- _typ = "int64index"
265
- _engine_type = libindex .Int64Engine
266
- _default_dtype = np .dtype (np .int64 )
267
- _dtype_validation_metadata = (is_signed_integer_dtype , "signed integer" )
268
-
269
-
270
- _uint64_descr_args = {
271
- "klass" : "UInt64Index" ,
272
- "ltype" : "unsigned integer" ,
273
- "dtype" : "uint64" ,
274
- "extra" : "" ,
275
- }
276
-
277
-
278
- class UInt64Index (IntegerIndex ):
279
- __doc__ = _num_index_shared_docs ["class_descr" ] % _uint64_descr_args
280
-
281
- _typ = "uint64index"
282
- _engine_type = libindex .UInt64Engine
283
- _default_dtype = np .dtype (np .uint64 )
284
- _dtype_validation_metadata = (is_unsigned_integer_dtype , "unsigned integer" )
285
-
286
- # ----------------------------------------------------------------
287
- # Indexing Methods
288
-
289
- @doc (Index ._convert_arr_indexer )
290
- def _convert_arr_indexer (self , keyarr ):
291
- # Cast the indexer to uint64 if possible so that the values returned
292
- # from indexing are also uint64.
293
- dtype = None
294
- if is_integer_dtype (keyarr ) or (
295
- lib .infer_dtype (keyarr , skipna = False ) == "integer"
296
- ):
297
- dtype = np .dtype (np .uint64 )
298
-
299
- return com .asarray_tuplesafe (keyarr , dtype = dtype )
300
-
301
-
302
- _float64_descr_args = {
303
- "klass" : "Float64Index" ,
304
- "dtype" : "float64" ,
305
- "ltype" : "float" ,
306
- "extra" : "" ,
307
- }
308
-
309
-
310
- class Float64Index (NumericIndex ):
311
- __doc__ = _num_index_shared_docs ["class_descr" ] % _float64_descr_args
312
-
313
- _typ = "float64index"
314
- _engine_type = libindex .Float64Engine
315
- _default_dtype = np .dtype (np .float64 )
316
- _dtype_validation_metadata = (is_float_dtype , "float" )
317
-
318
- @property
319
- def inferred_type (self ) -> str :
320
- """
321
- Always 'floating' for ``Float64Index``
322
- """
323
- return "floating"
324
-
325
- @doc (Index .astype )
326
- def astype (self , dtype , copy = True ):
327
- dtype = pandas_dtype (dtype )
328
- if needs_i8_conversion (dtype ):
329
- raise TypeError (
330
- f"Cannot convert Float64Index to dtype { dtype } ; integer "
331
- "values are required for conversion"
332
- )
333
- elif is_integer_dtype (dtype ) and not is_extension_array_dtype (dtype ):
334
- # TODO(jreback); this can change once we have an EA Index type
335
- # GH 13149
336
- arr = astype_nansafe (self ._values , dtype = dtype )
337
- return Int64Index (arr , name = self .name )
338
- return super ().astype (dtype , copy = copy )
339
-
340
- # ----------------------------------------------------------------
341
- # Indexing Methods
342
-
343
- @doc (Index ._should_fallback_to_positional )
344
- def _should_fallback_to_positional (self ) -> bool :
345
- return False
346
-
347
- @doc (Index ._convert_slice_indexer )
348
- def _convert_slice_indexer (self , key : slice , kind : str ):
349
- assert kind in ["loc" , "getitem" ]
350
-
351
- # We always treat __getitem__ slicing as label-based
352
- # translate to locations
353
- return self .slice_indexer (key .start , key .stop , key .step , kind = kind )
354
-
355
- # ----------------------------------------------------------------
356
-
357
- def _format_native_types (
358
- self , na_rep = "" , float_format = None , decimal = "." , quoting = None , ** kwargs
359
- ):
360
- from pandas .io .formats .format import FloatArrayFormatter
361
-
362
- formatter = FloatArrayFormatter (
363
- self ._values ,
364
- na_rep = na_rep ,
365
- float_format = float_format ,
366
- decimal = decimal ,
367
- quoting = quoting ,
368
- fixed_width = False ,
369
- )
370
- return formatter .get_result_as_array ()
371
-
372
208
373
209
_numindex_descr_args = {
374
210
"klass" : "NumIndex" ,
@@ -382,7 +218,6 @@ class NumIndex(NumericIndex):
382
218
__doc__ = _num_index_shared_docs ["class_descr" ] % _numindex_descr_args
383
219
384
220
_typ = "numindex"
385
- _default_dtype : np .dtype
386
221
_dtype_validation_metadata = (is_numeric_dtype , "numeric type" )
387
222
388
223
@cache_readonly
@@ -416,21 +251,13 @@ def inferred_type(self) -> str:
416
251
}[self .dtype .kind ]
417
252
418
253
@classmethod
419
- def _ensure_array (cls , data , dtype , copy : bool ) -> np .ndarray :
420
- """
421
- Ensure we have a valid array to pass to _simple_new.
422
- """
423
- arr = np .array (data , dtype = dtype , copy = copy )
424
- cls ._validate_dtype (arr .dtype )
425
- return arr
426
-
427
- @classmethod
428
- def _assert_safe_casting (cls , data , subarr ):
254
+ def _assert_safe_casting (cls , data , subarr ) -> None :
429
255
"""
430
256
Ensure incoming data can be represented with matching signed-ness.
431
257
"""
432
- if data .dtype .kind not in {"i" , "u" } and not np .array_equal (data , subarr ):
433
- raise TypeError ("Unsafe NumPy casting, you must explicitly cast" )
258
+ if is_integer_dtype (subarr .dtype ):
259
+ if not np .array_equal (data , subarr ):
260
+ raise TypeError ("Unsafe NumPy casting, you must explicitly cast" )
434
261
435
262
def __contains__ (self , key ) -> bool :
436
263
"""
@@ -450,11 +277,7 @@ def __contains__(self, key) -> bool:
450
277
451
278
@doc (Index .astype )
452
279
def astype (self , dtype , copy = True ):
453
- if is_categorical_dtype (dtype ):
454
- from pandas import CategoricalIndex
455
-
456
- return CategoricalIndex (self , name = self .name , dtype = dtype , copy = copy )
457
- elif is_float_dtype (dtype ):
280
+ if is_float_dtype (self .dtype ):
458
281
dtype = pandas_dtype (dtype )
459
282
if needs_i8_conversion (dtype ):
460
283
raise TypeError (
@@ -465,17 +288,52 @@ def astype(self, dtype, copy=True):
465
288
# TODO(jreback); this can change once we have an EA Index type
466
289
# GH 13149
467
290
arr = astype_nansafe (self ._values , dtype = dtype )
468
- return type (self )(arr , name = self .name , dtype = dtype )
291
+ if isinstance (self , Float64Index ):
292
+ return Int64Index (arr , name = self .name )
293
+ else :
294
+ return NumIndex (arr , name = self .name , dtype = dtype )
295
+ elif is_categorical_dtype (dtype ):
296
+ from pandas import CategoricalIndex
297
+
298
+ return CategoricalIndex (self , name = self .name , dtype = dtype , copy = copy )
469
299
470
300
return super ().astype (dtype , copy = copy )
471
301
302
+ # ----------------------------------------------------------------
303
+ # Indexing Methods
304
+
305
+ @doc (Index ._should_fallback_to_positional )
306
+ def _should_fallback_to_positional (self ) -> bool :
307
+ if self .inferred_type == "floating" :
308
+ return False
309
+
310
+ return super ()._should_fallback_to_positional ()
311
+
472
312
@doc (Index ._convert_slice_indexer )
473
313
def _convert_slice_indexer (self , key : slice , kind : str ):
474
- assert kind in ["loc" , "getitem" ]
314
+ if is_float_dtype (self .dtype ):
315
+ assert kind in ["loc" , "getitem" ]
316
+
317
+ # We always treat __getitem__ slicing as label-based
318
+ # translate to locations
319
+ return self .slice_indexer (key .start , key .stop , key .step , kind = kind )
320
+
321
+ return super ()._convert_slice_indexer (key , kind = kind )
322
+
323
+ @doc (Index ._convert_arr_indexer )
324
+ def _convert_arr_indexer (self , keyarr ) -> np .ndarray :
325
+ if is_unsigned_integer_dtype (self .dtype ):
326
+ # Cast the indexer to uint64 if possible so that the values returned
327
+ # from indexing are also uint64.
328
+ dtype = None
329
+ if is_integer_dtype (keyarr ) or (
330
+ lib .infer_dtype (keyarr , skipna = False ) == "integer"
331
+ ):
332
+ dtype = np .dtype (np .uint64 )
475
333
476
- # We always treat __getitem__ slicing as label-based
477
- # translate to locations
478
- return self . slice_indexer ( key . start , key . stop , key . step , kind = kind )
334
+ return com . asarray_tuplesafe ( keyarr , dtype = dtype )
335
+
336
+ return super (). _convert_arr_indexer ( keyarr )
479
337
480
338
# ----------------------------------------------------------------
481
339
@@ -502,3 +360,67 @@ def _format_native_types(
502
360
fixed_width = False ,
503
361
)
504
362
return formatter .get_result_as_array ()
363
+
364
+
365
+ _int64_descr_args = {
366
+ "klass" : "Int64Index" ,
367
+ "ltype" : "integer" ,
368
+ "dtype" : "int64" ,
369
+ "extra" : "" ,
370
+ }
371
+
372
+
373
+ class Int64Index (NumIndex ):
374
+ __doc__ = _num_index_shared_docs ["class_descr" ] % _int64_descr_args
375
+
376
+ _typ = "int64index"
377
+ _engine_type = libindex .Int64Engine
378
+ _default_dtype = np .dtype (np .int64 )
379
+ _dtype_validation_metadata = (is_signed_integer_dtype , "signed integer" )
380
+
381
+ @property
382
+ def asi8 (self ) -> np .ndarray :
383
+ # do not cache or you'll create a memory leak
384
+ warnings .warn (
385
+ "Index.asi8 is deprecated and will be removed in a future version" ,
386
+ FutureWarning ,
387
+ stacklevel = 2 ,
388
+ )
389
+ return self ._values .view (self ._default_dtype )
390
+
391
+
392
+ _uint64_descr_args = {
393
+ "klass" : "UInt64Index" ,
394
+ "ltype" : "unsigned integer" ,
395
+ "dtype" : "uint64" ,
396
+ "extra" : "" ,
397
+ }
398
+
399
+
400
+ class UInt64Index (NumIndex ):
401
+ __doc__ = _num_index_shared_docs ["class_descr" ] % _uint64_descr_args
402
+
403
+ _typ = "uint64index"
404
+ _engine_type = libindex .UInt64Engine
405
+ _default_dtype = np .dtype (np .uint64 )
406
+ _dtype_validation_metadata = (is_unsigned_integer_dtype , "unsigned integer" )
407
+
408
+ # ----------------------------------------------------------------
409
+ # Indexing Methods
410
+
411
+
412
+ _float64_descr_args = {
413
+ "klass" : "Float64Index" ,
414
+ "dtype" : "float64" ,
415
+ "ltype" : "float" ,
416
+ "extra" : "" ,
417
+ }
418
+
419
+
420
+ class Float64Index (NumIndex ):
421
+ __doc__ = _num_index_shared_docs ["class_descr" ] % _float64_descr_args
422
+
423
+ _typ = "float64index"
424
+ _engine_type = libindex .Float64Engine
425
+ _default_dtype = np .dtype (np .float64 )
426
+ _dtype_validation_metadata = (is_float_dtype , "float" )
0 commit comments