Coverage for /var/srv/projects/api.amasfac.comuna18.com/tmp/venv/lib/python3.9/site-packages/pandas/core/indexes/numeric.py: 43%
149 statements
« prev ^ index » next coverage.py v6.4.4, created at 2023-07-17 14:22 -0600
« prev ^ index » next coverage.py v6.4.4, created at 2023-07-17 14:22 -0600
1from __future__ import annotations
3from typing import (
4 Callable,
5 Hashable,
6)
7import warnings
9import numpy as np
11from pandas._libs import (
12 index as libindex,
13 lib,
14)
15from pandas._typing import (
16 Dtype,
17 npt,
18)
19from pandas.util._decorators import (
20 cache_readonly,
21 doc,
22)
23from pandas.util._exceptions import find_stack_level
25from pandas.core.dtypes.common import (
26 is_dtype_equal,
27 is_float_dtype,
28 is_integer_dtype,
29 is_numeric_dtype,
30 is_scalar,
31 is_signed_integer_dtype,
32 is_unsigned_integer_dtype,
33 pandas_dtype,
34)
35from pandas.core.dtypes.generic import ABCSeries
37from pandas.core.indexes.base import (
38 Index,
39 maybe_extract_name,
40)
43class NumericIndex(Index):
44 """
45 Immutable numeric sequence used for indexing and alignment.
47 The basic object storing axis labels for all pandas objects.
48 NumericIndex is a special case of `Index` with purely numpy int/uint/float labels.
50 .. versionadded:: 1.4.0
52 Parameters
53 ----------
54 data : array-like (1-dimensional)
55 dtype : NumPy dtype (default: None)
56 copy : bool
57 Make a copy of input ndarray.
58 name : object
59 Name to be stored in the index.
61 Attributes
62 ----------
63 None
65 Methods
66 -------
67 None
69 See Also
70 --------
71 Index : The base pandas Index type.
72 Int64Index : Index of purely int64 labels (deprecated).
73 UInt64Index : Index of purely uint64 labels (deprecated).
74 Float64Index : Index of purely float64 labels (deprecated).
76 Notes
77 -----
78 An NumericIndex instance can **only** contain numpy int64/32/16/8, uint64/32/16/8 or
79 float64/32/16 dtype. In particular, ``NumericIndex`` *can not* hold Pandas numeric
80 dtypes (:class:`Int64Dtype`, :class:`Int32Dtype` etc.).
81 """
83 _typ = "numericindex"
84 _values: np.ndarray
85 _default_dtype: np.dtype | None = None
86 _dtype_validation_metadata: tuple[Callable[..., bool], str] = (
87 is_numeric_dtype,
88 "numeric type",
89 )
90 _is_numeric_dtype = True
91 _can_hold_strings = False
92 _is_backward_compat_public_numeric_index: bool = True
94 _engine_types: dict[np.dtype, type[libindex.IndexEngine]] = {
95 np.dtype(np.int8): libindex.Int8Engine,
96 np.dtype(np.int16): libindex.Int16Engine,
97 np.dtype(np.int32): libindex.Int32Engine,
98 np.dtype(np.int64): libindex.Int64Engine,
99 np.dtype(np.uint8): libindex.UInt8Engine,
100 np.dtype(np.uint16): libindex.UInt16Engine,
101 np.dtype(np.uint32): libindex.UInt32Engine,
102 np.dtype(np.uint64): libindex.UInt64Engine,
103 np.dtype(np.float32): libindex.Float32Engine,
104 np.dtype(np.float64): libindex.Float64Engine,
105 np.dtype(np.complex64): libindex.Complex64Engine,
106 np.dtype(np.complex128): libindex.Complex128Engine,
107 }
109 @property
110 def _engine_type(self) -> type[libindex.IndexEngine]:
111 # error: Invalid index type "Union[dtype[Any], ExtensionDtype]" for
112 # "Dict[dtype[Any], Type[IndexEngine]]"; expected type "dtype[Any]"
113 return self._engine_types[self.dtype] # type: ignore[index]
115 @cache_readonly
116 def inferred_type(self) -> str:
117 return {
118 "i": "integer",
119 "u": "integer",
120 "f": "floating",
121 "c": "complex",
122 }[self.dtype.kind]
124 def __new__(
125 cls, data=None, dtype: Dtype | None = None, copy=False, name=None
126 ) -> NumericIndex:
127 name = maybe_extract_name(name, data, cls)
129 subarr = cls._ensure_array(data, dtype, copy)
130 return cls._simple_new(subarr, name=name)
132 @classmethod
133 def _ensure_array(cls, data, dtype, copy: bool):
134 """
135 Ensure we have a valid array to pass to _simple_new.
136 """
137 cls._validate_dtype(dtype)
139 if not isinstance(data, (np.ndarray, Index)):
140 # Coerce to ndarray if not already ndarray or Index
141 if is_scalar(data):
142 raise cls._scalar_data_error(data)
144 # other iterable of some kind
145 if not isinstance(data, (ABCSeries, list, tuple)):
146 data = list(data)
148 orig = data
149 data = np.asarray(data, dtype=dtype)
150 if dtype is None and data.dtype.kind == "f":
151 if cls is UInt64Index and (data >= 0).all():
152 # https://github.com/numpy/numpy/issues/19146
153 data = np.asarray(orig, dtype=np.uint64)
155 if issubclass(data.dtype.type, str):
156 cls._string_data_error(data)
158 dtype = cls._ensure_dtype(dtype)
160 if copy or not is_dtype_equal(data.dtype, dtype):
161 # TODO: the try/except below is because it's difficult to predict the error
162 # and/or error message from different combinations of data and dtype.
163 # Efforts to avoid this try/except welcome.
164 # See https://github.com/pandas-dev/pandas/pull/41153#discussion_r676206222
165 try:
166 subarr = np.array(data, dtype=dtype, copy=copy)
167 cls._validate_dtype(subarr.dtype)
168 except (TypeError, ValueError):
169 raise ValueError(f"data is not compatible with {cls.__name__}")
170 cls._assert_safe_casting(data, subarr)
171 else:
172 subarr = data
174 if subarr.ndim > 1:
175 # GH#13601, GH#20285, GH#27125
176 raise ValueError("Index data must be 1-dimensional")
178 subarr = np.asarray(subarr)
179 return subarr
181 @classmethod
182 def _validate_dtype(cls, dtype: Dtype | None) -> None:
183 if dtype is None:
184 return
186 validation_func, expected = cls._dtype_validation_metadata
187 if not validation_func(dtype):
188 raise ValueError(
189 f"Incorrect `dtype` passed: expected {expected}, received {dtype}"
190 )
192 @classmethod
193 def _ensure_dtype(cls, dtype: Dtype | None) -> np.dtype | None:
194 """
195 Ensure int64 dtype for Int64Index etc. but allow int32 etc. for NumericIndex.
197 Assumes dtype has already been validated.
198 """
199 if dtype is None:
200 return cls._default_dtype
202 dtype = pandas_dtype(dtype)
203 assert isinstance(dtype, np.dtype)
205 if cls._is_backward_compat_public_numeric_index:
206 # dtype for NumericIndex
207 return dtype
208 else:
209 # dtype for Int64Index, UInt64Index etc. Needed for backwards compat.
210 return cls._default_dtype
212 # ----------------------------------------------------------------
213 # Indexing Methods
215 # error: Decorated property not supported
216 @cache_readonly # type: ignore[misc]
217 @doc(Index._should_fallback_to_positional)
218 def _should_fallback_to_positional(self) -> bool:
219 return False
221 @doc(Index._convert_slice_indexer)
222 def _convert_slice_indexer(self, key: slice, kind: str, is_frame: bool = False):
223 # TODO(2.0): once #45324 deprecation is enforced we should be able
224 # to simplify this.
225 if is_float_dtype(self.dtype):
226 assert kind in ["loc", "getitem"]
228 # TODO: can we write this as a condition based on
229 # e.g. _should_fallback_to_positional?
230 # We always treat __getitem__ slicing as label-based
231 # translate to locations
232 return self.slice_indexer(key.start, key.stop, key.step)
234 return super()._convert_slice_indexer(key, kind=kind, is_frame=is_frame)
236 @doc(Index._maybe_cast_slice_bound)
237 def _maybe_cast_slice_bound(self, label, side: str, kind=lib.no_default):
238 assert kind in ["loc", "getitem", None, lib.no_default]
239 self._deprecated_arg(kind, "kind", "_maybe_cast_slice_bound")
241 # we will try to coerce to integers
242 return self._maybe_cast_indexer(label)
244 # ----------------------------------------------------------------
246 @doc(Index._shallow_copy)
247 def _shallow_copy(self, values, name: Hashable = lib.no_default):
248 if not self._can_hold_na and values.dtype.kind == "f":
249 name = self._name if name is lib.no_default else name
250 # Ensure we are not returning an Int64Index with float data:
251 return Float64Index._simple_new(values, name=name)
252 return super()._shallow_copy(values=values, name=name)
254 def _convert_tolerance(self, tolerance, target):
255 tolerance = super()._convert_tolerance(tolerance, target)
257 if not np.issubdtype(tolerance.dtype, np.number):
258 if tolerance.ndim > 0:
259 raise ValueError(
260 f"tolerance argument for {type(self).__name__} must contain "
261 "numeric elements if it is list type"
262 )
263 else:
264 raise ValueError(
265 f"tolerance argument for {type(self).__name__} must be numeric "
266 f"if it is a scalar: {repr(tolerance)}"
267 )
268 return tolerance
270 @classmethod
271 def _assert_safe_casting(cls, data: np.ndarray, subarr: np.ndarray) -> None:
272 """
273 Ensure incoming data can be represented with matching signed-ness.
275 Needed if the process of casting data from some accepted dtype to the internal
276 dtype(s) bears the risk of truncation (e.g. float to int).
277 """
278 if is_integer_dtype(subarr.dtype):
279 if not np.array_equal(data, subarr):
280 raise TypeError("Unsafe NumPy casting, you must explicitly cast")
282 def _format_native_types(
283 self, *, na_rep="", float_format=None, decimal=".", quoting=None, **kwargs
284 ) -> npt.NDArray[np.object_]:
285 from pandas.io.formats.format import FloatArrayFormatter
287 if is_float_dtype(self.dtype):
288 formatter = FloatArrayFormatter(
289 self._values,
290 na_rep=na_rep,
291 float_format=float_format,
292 decimal=decimal,
293 quoting=quoting,
294 fixed_width=False,
295 )
296 return formatter.get_result_as_array()
298 return super()._format_native_types(
299 na_rep=na_rep,
300 float_format=float_format,
301 decimal=decimal,
302 quoting=quoting,
303 **kwargs,
304 )
307_num_index_shared_docs = {}
310_num_index_shared_docs[
311 "class_descr"
312] = """
313 Immutable sequence used for indexing and alignment.
315 .. deprecated:: 1.4.0
316 In pandas v2.0 %(klass)s will be removed and :class:`NumericIndex` used instead.
317 %(klass)s will remain fully functional for the duration of pandas 1.x.
319 The basic object storing axis labels for all pandas objects.
320 %(klass)s is a special case of `Index` with purely %(ltype)s labels. %(extra)s.
322 Parameters
323 ----------
324 data : array-like (1-dimensional)
325 dtype : NumPy dtype (default: %(dtype)s)
326 copy : bool
327 Make a copy of input ndarray.
328 name : object
329 Name to be stored in the index.
331 Attributes
332 ----------
333 None
335 Methods
336 -------
337 None
339 See Also
340 --------
341 Index : The base pandas Index type.
342 NumericIndex : Index of numpy int/uint/float data.
344 Notes
345 -----
346 An Index instance can **only** contain hashable objects.
347"""
350class IntegerIndex(NumericIndex):
351 """
352 This is an abstract class for Int64Index, UInt64Index.
353 """
355 _is_backward_compat_public_numeric_index: bool = False
357 @property
358 def asi8(self) -> npt.NDArray[np.int64]:
359 # do not cache or you'll create a memory leak
360 warnings.warn(
361 "Index.asi8 is deprecated and will be removed in a future version.",
362 FutureWarning,
363 stacklevel=find_stack_level(),
364 )
365 return self._values.view(self._default_dtype)
368class Int64Index(IntegerIndex):
369 _index_descr_args = {
370 "klass": "Int64Index",
371 "ltype": "integer",
372 "dtype": "int64",
373 "extra": "",
374 }
375 __doc__ = _num_index_shared_docs["class_descr"] % _index_descr_args
377 _typ = "int64index"
378 _default_dtype = np.dtype(np.int64)
379 _dtype_validation_metadata = (is_signed_integer_dtype, "signed integer")
381 @property
382 def _engine_type(self) -> type[libindex.Int64Engine]:
383 return libindex.Int64Engine
386class UInt64Index(IntegerIndex):
387 _index_descr_args = {
388 "klass": "UInt64Index",
389 "ltype": "unsigned integer",
390 "dtype": "uint64",
391 "extra": "",
392 }
393 __doc__ = _num_index_shared_docs["class_descr"] % _index_descr_args
395 _typ = "uint64index"
396 _default_dtype = np.dtype(np.uint64)
397 _dtype_validation_metadata = (is_unsigned_integer_dtype, "unsigned integer")
399 @property
400 def _engine_type(self) -> type[libindex.UInt64Engine]:
401 return libindex.UInt64Engine
404class Float64Index(NumericIndex):
405 _index_descr_args = {
406 "klass": "Float64Index",
407 "dtype": "float64",
408 "ltype": "float",
409 "extra": "",
410 }
411 __doc__ = _num_index_shared_docs["class_descr"] % _index_descr_args
413 _typ = "float64index"
414 _default_dtype = np.dtype(np.float64)
415 _dtype_validation_metadata = (is_float_dtype, "float")
416 _is_backward_compat_public_numeric_index: bool = False
418 @property
419 def _engine_type(self) -> type[libindex.Float64Engine]:
420 return libindex.Float64Engine