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

1from __future__ import annotations 

2 

3from typing import ( 

4 Callable, 

5 Hashable, 

6) 

7import warnings 

8 

9import numpy as np 

10 

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 

24 

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 

36 

37from pandas.core.indexes.base import ( 

38 Index, 

39 maybe_extract_name, 

40) 

41 

42 

43class NumericIndex(Index): 

44 """ 

45 Immutable numeric sequence used for indexing and alignment. 

46 

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. 

49 

50 .. versionadded:: 1.4.0 

51 

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. 

60 

61 Attributes 

62 ---------- 

63 None 

64 

65 Methods 

66 ------- 

67 None 

68 

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). 

75 

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 """ 

82 

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 

93 

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 } 

108 

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] 

114 

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] 

123 

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) 

128 

129 subarr = cls._ensure_array(data, dtype, copy) 

130 return cls._simple_new(subarr, name=name) 

131 

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) 

138 

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) 

143 

144 # other iterable of some kind 

145 if not isinstance(data, (ABCSeries, list, tuple)): 

146 data = list(data) 

147 

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) 

154 

155 if issubclass(data.dtype.type, str): 

156 cls._string_data_error(data) 

157 

158 dtype = cls._ensure_dtype(dtype) 

159 

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 

173 

174 if subarr.ndim > 1: 

175 # GH#13601, GH#20285, GH#27125 

176 raise ValueError("Index data must be 1-dimensional") 

177 

178 subarr = np.asarray(subarr) 

179 return subarr 

180 

181 @classmethod 

182 def _validate_dtype(cls, dtype: Dtype | None) -> None: 

183 if dtype is None: 

184 return 

185 

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 ) 

191 

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. 

196 

197 Assumes dtype has already been validated. 

198 """ 

199 if dtype is None: 

200 return cls._default_dtype 

201 

202 dtype = pandas_dtype(dtype) 

203 assert isinstance(dtype, np.dtype) 

204 

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 

211 

212 # ---------------------------------------------------------------- 

213 # Indexing Methods 

214 

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 

220 

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"] 

227 

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) 

233 

234 return super()._convert_slice_indexer(key, kind=kind, is_frame=is_frame) 

235 

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") 

240 

241 # we will try to coerce to integers 

242 return self._maybe_cast_indexer(label) 

243 

244 # ---------------------------------------------------------------- 

245 

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) 

253 

254 def _convert_tolerance(self, tolerance, target): 

255 tolerance = super()._convert_tolerance(tolerance, target) 

256 

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 

269 

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. 

274 

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") 

281 

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 

286 

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() 

297 

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 ) 

305 

306 

307_num_index_shared_docs = {} 

308 

309 

310_num_index_shared_docs[ 

311 "class_descr" 

312] = """ 

313 Immutable sequence used for indexing and alignment. 

314 

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. 

318 

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. 

321 

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. 

330 

331 Attributes 

332 ---------- 

333 None 

334 

335 Methods 

336 ------- 

337 None 

338 

339 See Also 

340 -------- 

341 Index : The base pandas Index type. 

342 NumericIndex : Index of numpy int/uint/float data. 

343 

344 Notes 

345 ----- 

346 An Index instance can **only** contain hashable objects. 

347""" 

348 

349 

350class IntegerIndex(NumericIndex): 

351 """ 

352 This is an abstract class for Int64Index, UInt64Index. 

353 """ 

354 

355 _is_backward_compat_public_numeric_index: bool = False 

356 

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) 

366 

367 

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 

376 

377 _typ = "int64index" 

378 _default_dtype = np.dtype(np.int64) 

379 _dtype_validation_metadata = (is_signed_integer_dtype, "signed integer") 

380 

381 @property 

382 def _engine_type(self) -> type[libindex.Int64Engine]: 

383 return libindex.Int64Engine 

384 

385 

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 

394 

395 _typ = "uint64index" 

396 _default_dtype = np.dtype(np.uint64) 

397 _dtype_validation_metadata = (is_unsigned_integer_dtype, "unsigned integer") 

398 

399 @property 

400 def _engine_type(self) -> type[libindex.UInt64Engine]: 

401 return libindex.UInt64Engine 

402 

403 

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 

412 

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 

417 

418 @property 

419 def _engine_type(self) -> type[libindex.Float64Engine]: 

420 return libindex.Float64Engine