Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.11/site-packages/pandas/core/construction.py: 14%

Shortcuts on this page

r m x   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

274 statements  

1""" 

2Constructor functions intended to be shared by pd.array, Series.__init__, 

3and Index.__new__. 

4 

5These should not depend on core.internals. 

6""" 

7 

8from __future__ import annotations 

9 

10from typing import ( 

11 TYPE_CHECKING, 

12 Any, 

13 cast, 

14 overload, 

15) 

16 

17import numpy as np 

18from numpy import ma 

19 

20from pandas._config import using_string_dtype 

21 

22from pandas._libs import lib 

23from pandas._libs.tslibs import ( 

24 get_supported_dtype, 

25 is_supported_dtype, 

26) 

27from pandas.util._decorators import set_module 

28 

29from pandas.core.dtypes.base import ExtensionDtype 

30from pandas.core.dtypes.cast import ( 

31 construct_1d_arraylike_from_scalar, 

32 construct_1d_object_array_from_listlike, 

33 maybe_cast_to_datetime, 

34 maybe_cast_to_integer_array, 

35 maybe_promote, 

36) 

37from pandas.core.dtypes.common import ( 

38 ensure_object, 

39 is_list_like, 

40 is_object_dtype, 

41 pandas_dtype, 

42) 

43from pandas.core.dtypes.dtypes import ( 

44 BaseMaskedDtype, 

45 NumpyEADtype, 

46) 

47from pandas.core.dtypes.generic import ( 

48 ABCDataFrame, 

49 ABCExtensionArray, 

50 ABCIndex, 

51 ABCSeries, 

52) 

53from pandas.core.dtypes.missing import ( 

54 isna, 

55 na_value_for_dtype, 

56) 

57 

58import pandas.core.common as com 

59 

60if TYPE_CHECKING: 

61 from collections.abc import Sequence 

62 

63 from pandas._typing import ( 

64 AnyArrayLike, 

65 ArrayLike, 

66 Dtype, 

67 DtypeObj, 

68 T, 

69 ) 

70 

71 from pandas import ( 

72 Index, 

73 Series, 

74 ) 

75 from pandas.core.arrays import ( 

76 DatetimeArray, 

77 ExtensionArray, 

78 TimedeltaArray, 

79 ) 

80 

81 

82@set_module("pandas") 

83def array( 

84 data: Sequence[object] | AnyArrayLike, 

85 dtype: Dtype | None = None, 

86 copy: bool = True, 

87) -> ExtensionArray: 

88 """ 

89 Create an array. 

90 

91 This method constructs an array using pandas extension types when possible. 

92 If `dtype` is specified, it determines the type of array returned. Otherwise, 

93 pandas attempts to infer the appropriate dtype based on `data`. 

94 

95 Parameters 

96 ---------- 

97 data : Sequence of objects 

98 The scalars inside `data` should be instances of the 

99 scalar type for `dtype`. It's expected that `data` 

100 represents a 1-dimensional array of data. 

101 

102 When `data` is an Index or Series, the underlying array 

103 will be extracted from `data`. 

104 

105 dtype : str, np.dtype, or ExtensionDtype, optional 

106 The dtype to use for the array. This may be a NumPy 

107 dtype or an extension type registered with pandas using 

108 :meth:`pandas.api.extensions.register_extension_dtype`. 

109 

110 If not specified, there are two possibilities: 

111 

112 1. When `data` is a :class:`Series`, :class:`Index`, or 

113 :class:`ExtensionArray`, the `dtype` will be taken 

114 from the data. 

115 2. Otherwise, pandas will attempt to infer the `dtype` 

116 from the data. 

117 

118 Note that when `data` is a NumPy array, ``data.dtype`` is 

119 *not* used for inferring the array type. This is because 

120 NumPy cannot represent all the types of data that can be 

121 held in extension arrays. 

122 

123 Currently, pandas will infer an extension dtype for sequences of 

124 

125 ============================== ======================================= 

126 Scalar Type Array Type 

127 ============================== ======================================= 

128 :class:`pandas.Interval` :class:`pandas.arrays.IntervalArray` 

129 :class:`pandas.Period` :class:`pandas.arrays.PeriodArray` 

130 :class:`datetime.datetime` :class:`pandas.arrays.DatetimeArray` 

131 :class:`datetime.timedelta` :class:`pandas.arrays.TimedeltaArray` 

132 :class:`int` :class:`pandas.arrays.IntegerArray` 

133 :class:`float` :class:`pandas.arrays.FloatingArray` 

134 :class:`str` :class:`pandas.arrays.StringArray` or 

135 :class:`pandas.arrays.ArrowStringArray` 

136 :class:`bool` :class:`pandas.arrays.BooleanArray` 

137 ============================== ======================================= 

138 

139 The ExtensionArray created when the scalar type is :class:`str` is determined by 

140 ``pd.options.mode.string_storage`` if the dtype is not explicitly given. 

141 

142 For all other cases, NumPy's usual inference rules will be used. 

143 copy : bool, default True 

144 Whether to copy the data, even if not necessary. Depending 

145 on the type of `data`, creating the new array may require 

146 copying data, even if ``copy=False``. 

147 

148 Returns 

149 ------- 

150 ExtensionArray 

151 The newly created array. 

152 

153 Raises 

154 ------ 

155 ValueError 

156 When `data` is not 1-dimensional. 

157 

158 See Also 

159 -------- 

160 numpy.array : Construct a NumPy array. 

161 Series : Construct a pandas Series. 

162 Index : Construct a pandas Index. 

163 arrays.NumpyExtensionArray : ExtensionArray wrapping a NumPy array. 

164 Series.array : Extract the array stored within a Series. 

165 

166 Notes 

167 ----- 

168 Omitting the `dtype` argument means pandas will attempt to infer the 

169 best array type from the values in the data. As new array types are 

170 added by pandas and 3rd party libraries, the "best" array type may 

171 change. We recommend specifying `dtype` to ensure that 

172 

173 1. the correct array type for the data is returned 

174 2. the returned array type doesn't change as new extension types 

175 are added by pandas and third-party libraries 

176 

177 Additionally, if the underlying memory representation of the returned 

178 array matters, we recommend specifying the `dtype` as a concrete object 

179 rather than a string alias or allowing it to be inferred. For example, 

180 a future version of pandas or a 3rd-party library may include a 

181 dedicated ExtensionArray for string data. In this event, the following 

182 would no longer return a :class:`arrays.NumpyExtensionArray` backed by a 

183 NumPy array. 

184 

185 >>> pd.array(["a", "b"], dtype=str) 

186 <ArrowStringArray> 

187 ['a', 'b'] 

188 Length: 2, dtype: str 

189 

190 This would instead return the new ExtensionArray dedicated for string 

191 data. If you really need the new array to be backed by a NumPy array, 

192 specify that in the dtype. 

193 

194 >>> pd.array(["a", "b"], dtype=np.dtype("<U1")) 

195 <NumpyExtensionArray> 

196 ['a', 'b'] 

197 Length: 2, dtype: str32 

198 

199 pandas converts entries of a multidimensional sequence (excluding NumPy arrays) 

200 to its string representation if the ``dtype`` is a string data type. 

201 

202 >>> pd.array([[1], [2], [3]], dtype="str") 

203 <ArrowStringArray> 

204 ['[1]', '[2]', '[3]'] 

205 Length: 3, dtype: str 

206 

207 Finally, Pandas has arrays that mostly overlap with NumPy 

208 

209 * :class:`arrays.DatetimeArray` 

210 * :class:`arrays.TimedeltaArray` 

211 

212 When data with a ``datetime64[ns]`` or ``timedelta64[ns]`` dtype is 

213 passed, pandas will always return a ``DatetimeArray`` or ``TimedeltaArray`` 

214 rather than a ``NumpyExtensionArray``. This is for symmetry with the case of 

215 timezone-aware data, which NumPy does not natively support. 

216 

217 >>> pd.array(["2015", "2016"], dtype="datetime64[ns]") 

218 <DatetimeArray> 

219 ['2015-01-01 00:00:00', '2016-01-01 00:00:00'] 

220 Length: 2, dtype: datetime64[ns] 

221 

222 >>> pd.array(["1h", "2h"], dtype="timedelta64[ns]") 

223 <TimedeltaArray> 

224 ['0 days 01:00:00', '0 days 02:00:00'] 

225 Length: 2, dtype: timedelta64[ns] 

226 

227 Examples 

228 -------- 

229 If a dtype is not specified, pandas will infer the best dtype from the values. 

230 See the description of `dtype` for the types pandas infers for. 

231 

232 >>> pd.array([1, 2]) 

233 <IntegerArray> 

234 [1, 2] 

235 Length: 2, dtype: Int64 

236 

237 >>> pd.array([1, 2, np.nan]) 

238 <IntegerArray> 

239 [1, 2, <NA>] 

240 Length: 3, dtype: Int64 

241 

242 >>> pd.array([1.1, 2.2]) 

243 <FloatingArray> 

244 [1.1, 2.2] 

245 Length: 2, dtype: Float64 

246 

247 >>> pd.array(["a", None, "c"]) 

248 <ArrowStringArray> 

249 ['a', <NA>, 'c'] 

250 Length: 3, dtype: string 

251 

252 >>> with pd.option_context("string_storage", "python"): 

253 ... arr = pd.array(["a", None, "c"]) 

254 >>> arr 

255 <StringArray> 

256 ['a', <NA>, 'c'] 

257 Length: 3, dtype: string 

258 

259 >>> pd.array([pd.Period("2000", freq="D"), pd.Period("2000", freq="D")]) 

260 <PeriodArray> 

261 ['2000-01-01', '2000-01-01'] 

262 Length: 2, dtype: period[D] 

263 

264 You can use the string alias for `dtype` 

265 

266 >>> pd.array(["a", "b", "a"], dtype="category") 

267 ['a', 'b', 'a'] 

268 Categories (2, str): ['a', 'b'] 

269 

270 Or specify the actual dtype 

271 

272 >>> pd.array( 

273 ... ["a", "b", "a"], dtype=pd.CategoricalDtype(["a", "b", "c"], ordered=True) 

274 ... ) 

275 ['a', 'b', 'a'] 

276 Categories (3, str): ['a' < 'b' < 'c'] 

277 

278 If pandas does not infer a dedicated extension type a 

279 :class:`arrays.NumpyExtensionArray` is returned. 

280 

281 >>> pd.array([1 + 1j, 3 + 2j]) 

282 <NumpyExtensionArray> 

283 [(1+1j), (3+2j)] 

284 Length: 2, dtype: complex128 

285 

286 As mentioned in the "Notes" section, new extension types may be added 

287 in the future (by pandas or 3rd party libraries), causing the return 

288 value to no longer be a :class:`arrays.NumpyExtensionArray`. Specify the 

289 `dtype` as a NumPy dtype if you need to ensure there's no future change in 

290 behavior. 

291 

292 >>> pd.array([1, 2], dtype=np.dtype("int32")) 

293 <NumpyExtensionArray> 

294 [1, 2] 

295 Length: 2, dtype: int32 

296 

297 `data` must be 1-dimensional. A ValueError is raised when the input 

298 has the wrong dimensionality. 

299 

300 >>> pd.array(1) 

301 Traceback (most recent call last): 

302 ... 

303 ValueError: Cannot pass scalar '1' to 'pandas.array'. 

304 """ 

305 from pandas.core.arrays import ( 

306 BooleanArray, 

307 DatetimeArray, 

308 ExtensionArray, 

309 FloatingArray, 

310 IntegerArray, 

311 NumpyExtensionArray, 

312 TimedeltaArray, 

313 ) 

314 from pandas.core.arrays.string_ import StringDtype 

315 

316 if lib.is_scalar(data): 

317 msg = f"Cannot pass scalar '{data}' to 'pandas.array'." 

318 raise ValueError(msg) 

319 elif isinstance(data, ABCDataFrame): 

320 raise TypeError("Cannot pass DataFrame to 'pandas.array'") 

321 

322 if dtype is None and isinstance(data, (ABCSeries, ABCIndex, ExtensionArray)): 

323 # Note: we exclude np.ndarray here, will do type inference on it 

324 dtype = data.dtype 

325 

326 data = extract_array(data, extract_numpy=True) 

327 

328 # Handle numpy masked arrays: convert masked values to NA 

329 # GH#63879 

330 if isinstance(data, ma.MaskedArray): 

331 if data.dtype.names is not None: 

332 raise ValueError( 

333 "Cannot construct an array from an ndarray with compound dtype. " 

334 "Use DataFrame instead." 

335 ) 

336 mask = ma.getmask(data) 

337 if mask is ma.nomask: 

338 # Avoid materializing an all-False mask. 

339 data = np.asarray(data) 

340 else: 

341 try: 

342 masked_cls = BaseMaskedDtype.from_numpy_dtype( 

343 data.dtype 

344 ).construct_array_type() 

345 except (KeyError, NotImplementedError): 

346 # No nullable masked dtype for this kind. 

347 if data.dtype.char in "SU": 

348 data = lib.ensure_string_array(np.asarray(data.data)) 

349 data[mask] = np.nan 

350 else: 

351 # datetime64/timedelta64 use NaT; float16/complex/object NaN. 

352 # Argument to "filled" of "MaskedArray" has incompatible type...; 

353 # expected "complex | str | bytes | generic[Any] | None" 

354 data = data.filled( 

355 na_value_for_dtype(data.dtype, compat=False) # type: ignore[arg-type] 

356 ) 

357 else: 

358 # Argument 2 to "BaseMaskedArray" has incompatible type...; 

359 # expected "ndarray[tuple[Any, ...], dtype[numpy.bool[builtins.bool]]]" 

360 data = masked_cls(np.asarray(data.data), mask, copy=copy) # type: ignore[arg-type] 

361 

362 # this returns None for not-found dtypes. 

363 if dtype is not None: 

364 dtype = pandas_dtype(dtype) 

365 

366 if isinstance(data, ExtensionArray) and (dtype is None or data.dtype == dtype): 

367 # e.g. TimedeltaArray[s], avoid casting to NumpyExtensionArray 

368 if copy: 

369 return data.copy() 

370 return data 

371 

372 if isinstance(dtype, ExtensionDtype): 

373 cls = dtype.construct_array_type() 

374 return cls._from_sequence(data, dtype=dtype, copy=copy) 

375 

376 if dtype is None: 

377 was_ndarray = isinstance(data, np.ndarray) 

378 # error: Item "Sequence[object]" of "Sequence[object] | ExtensionArray | 

379 # ndarray[Any, Any]" has no attribute "dtype" 

380 if not was_ndarray or data.dtype == object: # type: ignore[union-attr] 

381 result = lib.maybe_convert_objects( 

382 ensure_object(data), 

383 convert_non_numeric=True, 

384 convert_to_nullable_dtype=True, 

385 dtype_if_all_nat=np.dtype("M8[s]"), 

386 ) 

387 result = ensure_wrapped_if_datetimelike(result) 

388 if isinstance(result, np.ndarray): 

389 if len(result) == 0 and not was_ndarray: 

390 # e.g. empty list 

391 return FloatingArray._from_sequence(data, dtype="Float64") 

392 return NumpyExtensionArray._from_sequence( 

393 data, dtype=result.dtype, copy=copy 

394 ) 

395 # We know result is an ExtensionArray here, but mypy doesn't 

396 assert isinstance(result, ExtensionArray) 

397 if result is data and copy: 

398 return result.copy() 

399 return result 

400 

401 data = cast("np.ndarray", data) 

402 result = ensure_wrapped_if_datetimelike(data) 

403 if result is not data: 

404 result = cast("DatetimeArray | TimedeltaArray", result) 

405 if copy and result.dtype == data.dtype: 

406 return result.copy() 

407 return result 

408 

409 if data.dtype.kind in "SU": 

410 # StringArray/ArrowStringArray depending on pd.options.mode.string_storage 

411 dtype = StringDtype() 

412 cls = dtype.construct_array_type() 

413 return cls._from_sequence(data, dtype=dtype, copy=copy) 

414 

415 elif data.dtype.kind in "iu": 

416 dtype = IntegerArray._dtype_cls._get_dtype_mapping()[data.dtype] 

417 return IntegerArray._from_sequence(data, dtype=dtype, copy=copy) 

418 elif data.dtype.kind == "f": 

419 # GH#44715 Exclude np.float16 bc FloatingArray does not support it; 

420 # we will fall back to NumpyExtensionArray. 

421 if data.dtype == np.float16: 

422 return NumpyExtensionArray._from_sequence( 

423 data, dtype=data.dtype, copy=copy 

424 ) 

425 dtype = FloatingArray._dtype_cls._get_dtype_mapping()[data.dtype] 

426 return FloatingArray._from_sequence(data, dtype=dtype, copy=copy) 

427 

428 elif data.dtype.kind == "b": 

429 return BooleanArray._from_sequence(data, dtype="boolean", copy=copy) 

430 else: 

431 # e.g. complex 

432 return NumpyExtensionArray._from_sequence(data, dtype=data.dtype, copy=copy) 

433 

434 # Pandas overrides NumPy for 

435 # 1. datetime64[ns,us,ms,s] 

436 # 2. timedelta64[ns,us,ms,s] 

437 # so that a DatetimeArray is returned. 

438 if lib.is_np_dtype(dtype, "M") and is_supported_dtype(dtype): 

439 return DatetimeArray._from_sequence(data, dtype=dtype, copy=copy) 

440 if lib.is_np_dtype(dtype, "m") and is_supported_dtype(dtype): 

441 return TimedeltaArray._from_sequence(data, dtype=dtype, copy=copy) 

442 

443 elif lib.is_np_dtype(dtype, "mM"): 

444 raise ValueError( 

445 # GH#53817 

446 r"datetime64 and timedelta64 dtype resolutions other than " 

447 r"'s', 'ms', 'us', and 'ns' are no longer supported." 

448 ) 

449 

450 return NumpyExtensionArray._from_sequence(data, dtype=dtype, copy=copy) 

451 

452 

453_typs = frozenset( 

454 { 

455 "index", 

456 "rangeindex", 

457 "multiindex", 

458 "datetimeindex", 

459 "timedeltaindex", 

460 "periodindex", 

461 "categoricalindex", 

462 "intervalindex", 

463 "series", 

464 } 

465) 

466 

467 

468@overload 

469def extract_array( 

470 obj: Series | Index, extract_numpy: bool = ..., extract_range: bool = ... 

471) -> ArrayLike: ... 

472 

473 

474@overload 

475def extract_array( 

476 obj: T, extract_numpy: bool = ..., extract_range: bool = ... 

477) -> T | ArrayLike: ... 

478 

479 

480def extract_array( 

481 obj: T, extract_numpy: bool = False, extract_range: bool = False 

482) -> T | ArrayLike: 

483 """ 

484 Extract the ndarray or ExtensionArray from a Series or Index. 

485 

486 For all other types, `obj` is just returned as is. 

487 

488 Parameters 

489 ---------- 

490 obj : object 

491 For Series / Index, the underlying ExtensionArray is unboxed. 

492 

493 extract_numpy : bool, default False 

494 Whether to extract the ndarray from a NumpyExtensionArray. 

495 

496 extract_range : bool, default False 

497 If we have a RangeIndex, return range._values if True 

498 (which is a materialized integer ndarray), otherwise return unchanged. 

499 

500 Returns 

501 ------- 

502 arr : object 

503 

504 Examples 

505 -------- 

506 >>> extract_array(pd.Series(["a", "b", "c"], dtype="category")) 

507 ['a', 'b', 'c'] 

508 Categories (3, str): ['a', 'b', 'c'] 

509 

510 Other objects like lists, arrays, and DataFrames are just passed through. 

511 

512 >>> extract_array([1, 2, 3]) 

513 [1, 2, 3] 

514 

515 For an ndarray-backed Series / Index the ndarray is returned. 

516 

517 >>> extract_array(pd.Series([1, 2, 3])) 

518 array([1, 2, 3]) 

519 

520 To extract all the way down to the ndarray, pass ``extract_numpy=True``. 

521 

522 >>> extract_array(pd.Series([1, 2, 3]), extract_numpy=True) 

523 array([1, 2, 3]) 

524 """ 

525 typ = getattr(obj, "_typ", None) 

526 if typ in _typs: 

527 # i.e. isinstance(obj, (ABCIndex, ABCSeries)) 

528 if typ == "rangeindex": 

529 if extract_range: 

530 # error: "T" has no attribute "_values" 

531 return obj._values # type: ignore[attr-defined] 

532 return obj 

533 

534 # error: "T" has no attribute "_values" 

535 return obj._values # type: ignore[attr-defined] 

536 

537 elif extract_numpy and typ == "npy_extension": 

538 # i.e. isinstance(obj, ABCNumpyExtensionArray) 

539 # error: "T" has no attribute "to_numpy" 

540 return obj.to_numpy() # type: ignore[attr-defined] 

541 

542 return obj 

543 

544 

545def ensure_wrapped_if_datetimelike(arr): 

546 """ 

547 Wrap datetime64 and timedelta64 ndarrays in DatetimeArray/TimedeltaArray. 

548 """ 

549 if isinstance(arr, np.ndarray): 

550 if arr.dtype.kind == "M": 

551 from pandas.core.arrays import DatetimeArray 

552 

553 dtype = get_supported_dtype(arr.dtype) 

554 return DatetimeArray._from_sequence(arr, dtype=dtype) 

555 

556 elif arr.dtype.kind == "m": 

557 from pandas.core.arrays import TimedeltaArray 

558 

559 dtype = get_supported_dtype(arr.dtype) 

560 return TimedeltaArray._from_sequence(arr, dtype=dtype) 

561 

562 return arr 

563 

564 

565def sanitize_masked_array(data: ma.MaskedArray) -> np.ndarray: 

566 """ 

567 Convert numpy MaskedArray to a plain ndarray with the masked entries filled. 

568 """ 

569 mask = ma.getmaskarray(data) 

570 if mask.any(): 

571 dtype, fill_value = maybe_promote(data.dtype, np.nan) 

572 data = ma.asarray(data.astype(dtype, copy=True)) 

573 data.soften_mask() # set hardmask False if it was True 

574 data[mask] = fill_value 

575 else: 

576 data = data.copy() 

577 return np.asarray(data) 

578 

579 

580def sanitize_array( 

581 data, 

582 index: Index | None, 

583 dtype: DtypeObj | None = None, 

584 copy: bool = False, 

585 *, 

586 allow_2d: bool = False, 

587) -> ArrayLike: 

588 """ 

589 Sanitize input data to an ndarray or ExtensionArray, copy if specified, 

590 coerce to the dtype if specified. 

591 

592 Parameters 

593 ---------- 

594 data : Any 

595 index : Index or None, default None 

596 dtype : np.dtype, ExtensionDtype, or None, default None 

597 copy : bool, default False 

598 allow_2d : bool, default False 

599 If False, raise if we have a 2D Arraylike. 

600 

601 Returns 

602 ------- 

603 np.ndarray or ExtensionArray 

604 """ 

605 original_dtype = dtype 

606 if isinstance(data, ma.MaskedArray): 

607 data = sanitize_masked_array(data) 

608 

609 if isinstance(dtype, NumpyEADtype): 

610 # Avoid ending up with a NumpyExtensionArray 

611 dtype = dtype.numpy_dtype 

612 

613 infer_object = not isinstance(data, (ABCIndex, ABCSeries)) 

614 

615 # extract ndarray or ExtensionArray, ensure we have no NumpyExtensionArray 

616 data = extract_array(data, extract_numpy=True, extract_range=True) 

617 

618 if isinstance(data, np.ndarray) and data.ndim == 0: 

619 if dtype is None: 

620 dtype = data.dtype 

621 data = lib.item_from_zerodim(data) 

622 elif isinstance(data, range): 

623 # GH#16804 

624 data = range_to_ndarray(data) 

625 copy = False 

626 

627 if not is_list_like(data): 

628 if index is None: 

629 raise ValueError("index must be specified when data is not list-like") 

630 if isinstance(data, str) and using_string_dtype() and original_dtype is None: 

631 from pandas.core.arrays.string_ import StringDtype 

632 

633 dtype = StringDtype(na_value=np.nan) 

634 data = construct_1d_arraylike_from_scalar(data, len(index), dtype) 

635 

636 return data 

637 

638 elif isinstance(data, ABCExtensionArray): 

639 # it is already ensured above this is not a NumpyExtensionArray 

640 # Until GH#49309 is fixed this check needs to come before the 

641 # ExtensionDtype check 

642 if dtype is not None: 

643 subarr = data.astype(dtype, copy=copy) 

644 elif copy: 

645 subarr = data.copy() 

646 else: 

647 subarr = data 

648 

649 elif isinstance(dtype, ExtensionDtype): 

650 # create an extension array from its dtype 

651 _sanitize_non_ordered(data) 

652 cls = dtype.construct_array_type() 

653 if not hasattr(data, "__array__"): 

654 data = list(data) 

655 subarr = cls._from_sequence(data, dtype=dtype, copy=copy) 

656 

657 # GH#846 

658 elif isinstance(data, np.ndarray): 

659 if isinstance(data, np.matrix): 

660 data = data.A 

661 

662 if dtype is None: 

663 subarr = data 

664 if data.dtype == object and infer_object: 

665 subarr = lib.maybe_convert_objects( 

666 data, 

667 # Here we do not convert numeric dtypes, as if we wanted that, 

668 # numpy would have done it for us. 

669 convert_numeric=False, 

670 convert_non_numeric=True, 

671 convert_to_nullable_dtype=False, 

672 dtype_if_all_nat=np.dtype("M8[s]"), 

673 ) 

674 elif data.dtype.kind == "U" and using_string_dtype(): 

675 from pandas.core.arrays.string_ import StringDtype 

676 

677 dtype = StringDtype(na_value=np.nan) 

678 subarr = dtype.construct_array_type()._from_sequence(data, dtype=dtype) 

679 

680 if ( 

681 subarr is data 

682 or (subarr.dtype == "str" and subarr.dtype.storage == "python") # type: ignore[union-attr] 

683 ) and copy: 

684 subarr = subarr.copy() 

685 

686 else: 

687 # we will try to copy by-definition here 

688 subarr = _try_cast(data, dtype, copy) 

689 

690 elif hasattr(data, "__array__"): 

691 # e.g. dask array GH#38645 

692 if not copy: 

693 data = np.asarray(data) 

694 else: 

695 data = np.array(data, copy=copy) 

696 return sanitize_array( 

697 data, 

698 index=index, 

699 dtype=dtype, 

700 copy=False, 

701 allow_2d=allow_2d, 

702 ) 

703 

704 else: 

705 _sanitize_non_ordered(data) 

706 # materialize e.g. generators, convert e.g. tuples, abc.ValueView 

707 data = list(data) 

708 

709 if len(data) == 0 and dtype is None: 

710 # We default to float64, matching numpy 

711 subarr = np.array([], dtype=np.float64) 

712 

713 elif dtype is not None: 

714 subarr = _try_cast(data, dtype, copy) 

715 

716 else: 

717 subarr = construct_1d_object_array_from_listlike(data) 

718 subarr = lib.maybe_convert_objects( 

719 subarr, 

720 convert_non_numeric=True, 

721 dtype_if_all_nat=np.dtype("M8[s]"), 

722 ) 

723 

724 subarr = _sanitize_ndim(subarr, data, dtype, index, allow_2d=allow_2d) 

725 

726 if isinstance(subarr, np.ndarray): 

727 # at this point we should have dtype be None or subarr.dtype == dtype 

728 dtype = cast("np.dtype", dtype) 

729 subarr = _sanitize_str_dtypes(subarr, data, dtype, copy) 

730 

731 return subarr 

732 

733 

734def range_to_ndarray(rng: range) -> np.ndarray: 

735 """ 

736 Cast a range object to ndarray. 

737 """ 

738 # GH#30171 perf avoid realizing range as a list in np.array 

739 try: 

740 arr = np.arange(rng.start, rng.stop, rng.step, dtype="int64") 

741 except OverflowError: 

742 # GH#30173 handling for ranges that overflow int64 

743 if (rng.start >= 0 and rng.step > 0) or (rng.step < 0 <= rng.stop): 

744 try: 

745 arr = np.arange(rng.start, rng.stop, rng.step, dtype="uint64") 

746 except OverflowError: 

747 arr = construct_1d_object_array_from_listlike(list(rng)) 

748 else: 

749 arr = construct_1d_object_array_from_listlike(list(rng)) 

750 return arr 

751 

752 

753def _sanitize_non_ordered(data) -> None: 

754 """ 

755 Raise only for unordered sets, e.g., not for dict_keys 

756 """ 

757 if isinstance(data, (set, frozenset)): 

758 raise TypeError(f"'{type(data).__name__}' type is unordered") 

759 

760 

761def _sanitize_ndim( 

762 result: ArrayLike, 

763 data, 

764 dtype: DtypeObj | None, 

765 index: Index | None, 

766 *, 

767 allow_2d: bool = False, 

768) -> ArrayLike: 

769 """ 

770 Ensure we have a 1-dimensional result array. 

771 """ 

772 if getattr(result, "ndim", 0) == 0: 

773 raise ValueError("result should be arraylike with ndim > 0") 

774 

775 if result.ndim == 1: 

776 # the result that we want 

777 result = _maybe_repeat(result, index) 

778 

779 elif result.ndim > 1: 

780 if isinstance(data, np.ndarray): 

781 if allow_2d: 

782 return result 

783 raise ValueError( 

784 f"Data must be 1-dimensional, got ndarray of shape {data.shape} instead" 

785 ) 

786 elif allow_2d and isinstance(result, ABCExtensionArray): 

787 # e.g. test_2d_ea_with_dtype_cast 

788 return result 

789 if is_object_dtype(dtype) and isinstance(dtype, ExtensionDtype): 

790 # i.e. NumpyEADtype("O") 

791 

792 result = com.asarray_tuplesafe(data, dtype=np.dtype("object")) 

793 cls = dtype.construct_array_type() 

794 result = cls._from_sequence(result, dtype=dtype) 

795 else: 

796 # error: Argument "dtype" to "asarray_tuplesafe" has incompatible type 

797 # "Union[dtype[Any], ExtensionDtype, None]"; expected "Union[str, 

798 # dtype[Any], None]" 

799 result = com.asarray_tuplesafe(data, dtype=dtype) # type: ignore[arg-type] 

800 return result 

801 

802 

803def _sanitize_str_dtypes( 

804 result: np.ndarray, data, dtype: np.dtype | None, copy: bool 

805) -> np.ndarray: 

806 """ 

807 Ensure we have a dtype that is supported by pandas. 

808 """ 

809 

810 # This is to prevent mixed-type Series getting all casted to 

811 # NumPy string type, e.g. NaN --> '-1#IND'. 

812 if issubclass(result.dtype.type, str): 

813 # GH#16605 

814 # If not empty convert the data to dtype 

815 # GH#19853: If data is a scalar, result has already the result 

816 if not lib.is_scalar(data): 

817 if not np.all(isna(data)): 

818 data = np.asarray(data, dtype=dtype) 

819 if not copy: 

820 result = np.asarray(data, dtype=object) 

821 else: 

822 result = np.array(data, dtype=object, copy=copy) 

823 return result 

824 

825 

826def _maybe_repeat(arr: ArrayLike, index: Index | None) -> ArrayLike: 

827 """ 

828 If we have a length-1 array and an index describing how long we expect 

829 the result to be, repeat the array. 

830 """ 

831 if index is not None: 

832 if 1 == len(arr) != len(index): 

833 arr = arr.repeat(len(index)) 

834 return arr 

835 

836 

837def _try_cast( 

838 arr: list[Any] | np.ndarray, 

839 dtype: np.dtype, 

840 copy: bool, 

841) -> ArrayLike: 

842 """ 

843 Convert input to numpy ndarray and optionally cast to a given dtype. 

844 

845 Parameters 

846 ---------- 

847 arr : ndarray or list 

848 Excludes: ExtensionArray, Series, Index. 

849 dtype : np.dtype 

850 copy : bool 

851 If False, don't copy the data if not needed. 

852 

853 Returns 

854 ------- 

855 np.ndarray or ExtensionArray 

856 """ 

857 is_ndarray = isinstance(arr, np.ndarray) 

858 

859 if dtype == object: 

860 if not is_ndarray: 

861 subarr = construct_1d_object_array_from_listlike(arr) 

862 return subarr 

863 return ensure_wrapped_if_datetimelike(arr).astype(dtype, copy=copy) 

864 

865 elif dtype.kind == "U": 

866 # TODO: test cases with arr.dtype.kind in "mM" 

867 if is_ndarray: 

868 arr = cast("np.ndarray", arr) 

869 shape = arr.shape 

870 if arr.ndim > 1: 

871 arr = arr.ravel() 

872 else: 

873 shape = (len(arr),) 

874 return lib.ensure_string_array(arr, convert_na_value=False, copy=copy).reshape( 

875 shape 

876 ) 

877 

878 elif dtype.kind in "mM": 

879 if is_ndarray: 

880 arr = cast("np.ndarray", arr) 

881 if arr.ndim == 2 and arr.shape[1] == 1: 

882 # GH#60081: DataFrame Constructor converts 1D data to array of 

883 # shape (N, 1), but maybe_cast_to_datetime assumes 1D input 

884 return maybe_cast_to_datetime(arr[:, 0], dtype).reshape(arr.shape) 

885 return maybe_cast_to_datetime(arr, dtype) 

886 

887 # GH#15832: Check if we are requesting a numeric dtype and 

888 # that we can convert the data to the requested dtype. 

889 elif dtype.kind in "iu": 

890 # this will raise if we have e.g. floats 

891 

892 subarr = maybe_cast_to_integer_array(arr, dtype) 

893 elif not copy: 

894 subarr = np.asarray(arr, dtype=dtype) 

895 else: 

896 subarr = np.array(arr, dtype=dtype, copy=copy) 

897 

898 return subarr