1"""
2Common type operations.
3"""
4
5from __future__ import annotations
6
7from typing import (
8 TYPE_CHECKING,
9 Any,
10)
11import warnings
12
13import numpy as np
14
15from pandas._config import using_string_dtype
16
17from pandas._libs import (
18 Interval,
19 Period,
20 algos,
21 lib,
22)
23from pandas._libs.tslibs import conversion
24from pandas.errors import Pandas4Warning
25from pandas.util._decorators import set_module
26from pandas.util._exceptions import find_stack_level
27
28from pandas.core.dtypes.base import _registry as registry
29from pandas.core.dtypes.dtypes import (
30 CategoricalDtype,
31 DatetimeTZDtype,
32 ExtensionDtype,
33 IntervalDtype,
34 PeriodDtype,
35 SparseDtype,
36)
37from pandas.core.dtypes.generic import ABCIndex
38from pandas.core.dtypes.inference import (
39 is_array_like,
40 is_bool,
41 is_complex,
42 is_dataclass,
43 is_decimal,
44 is_dict_like,
45 is_file_like,
46 is_float,
47 is_hashable,
48 is_integer,
49 is_iterator,
50 is_list_like,
51 is_named_tuple,
52 is_nested_list_like,
53 is_number,
54 is_re,
55 is_re_compilable,
56 is_scalar,
57 is_sequence,
58)
59
60if TYPE_CHECKING:
61 from collections.abc import Callable
62
63 from pandas._typing import (
64 ArrayLike,
65 DtypeObj,
66 )
67
68DT64NS_DTYPE = conversion.DT64NS_DTYPE
69TD64NS_DTYPE = conversion.TD64NS_DTYPE
70INT64_DTYPE = np.dtype(np.int64)
71
72# oh the troubles to reduce import time
73_is_scipy_sparse: Callable[[ArrayLike], bool] | None = None
74
75ensure_float64 = algos.ensure_float64
76ensure_int64 = algos.ensure_int64
77ensure_int32 = algos.ensure_int32
78ensure_int16 = algos.ensure_int16
79ensure_int8 = algos.ensure_int8
80ensure_platform_int = algos.ensure_platform_int
81ensure_object = algos.ensure_object
82ensure_uint64 = algos.ensure_uint64
83
84
85def ensure_str(value: bytes | Any) -> str:
86 """
87 Ensure that bytes and non-strings get converted into ``str`` objects.
88 """
89 if isinstance(value, bytes):
90 value = value.decode("utf-8")
91 elif not isinstance(value, str):
92 value = str(value)
93 return value
94
95
96def ensure_python_int(value: int | np.integer) -> int:
97 """
98 Ensure that a value is a python int.
99
100 Parameters
101 ----------
102 value: int or numpy.integer
103
104 Returns
105 -------
106 int
107
108 Raises
109 ------
110 TypeError: if the value isn't an int or can't be converted to one.
111 """
112 if not (is_integer(value) or is_float(value)):
113 if not is_scalar(value):
114 raise TypeError(
115 f"Value needs to be a scalar value, was type {type(value).__name__}"
116 )
117 raise TypeError(f"Wrong type {type(value)} for value {value}")
118 try:
119 new_value = int(value)
120 assert new_value == value
121 except (TypeError, ValueError, AssertionError) as err:
122 raise TypeError(f"Wrong type {type(value)} for value {value}") from err
123 return new_value
124
125
126def classes(*klasses) -> Callable:
127 """Evaluate if the tipo is a subclass of the klasses."""
128 return lambda tipo: issubclass(tipo, klasses)
129
130
131def _classes_and_not_datetimelike(*klasses) -> Callable:
132 """
133 Evaluate if the tipo is a subclass of the klasses
134 and not a datetimelike.
135 """
136 return lambda tipo: (
137 issubclass(tipo, klasses)
138 and not issubclass(tipo, (np.datetime64, np.timedelta64))
139 )
140
141
142@set_module("pandas.api.types")
143def is_object_dtype(arr_or_dtype) -> bool:
144 """
145 Check whether an array-like or dtype is of the object dtype.
146
147 This method examines the input to determine if it is of the
148 object data type. Object dtype is a generic data type that can
149 hold any Python objects, including strings, lists, and custom
150 objects.
151
152 Parameters
153 ----------
154 arr_or_dtype : array-like or dtype
155 The array-like or dtype to check.
156
157 Returns
158 -------
159 boolean
160 Whether or not the array-like or dtype is of the object dtype.
161
162 See Also
163 --------
164 api.types.is_numeric_dtype : Check whether the provided array or dtype is of a
165 numeric dtype.
166 api.types.is_string_dtype : Check whether the provided array or dtype is of
167 the string dtype.
168 api.types.is_bool_dtype : Check whether the provided array or dtype is of a
169 boolean dtype.
170
171 Examples
172 --------
173 >>> from pandas.api.types import is_object_dtype
174 >>> is_object_dtype(object)
175 True
176 >>> is_object_dtype(int)
177 False
178 >>> is_object_dtype(np.array([], dtype=object))
179 True
180 >>> is_object_dtype(np.array([], dtype=int))
181 False
182 >>> is_object_dtype([1, 2, 3])
183 False
184 """
185 return _is_dtype_type(arr_or_dtype, classes(np.object_))
186
187
188@set_module("pandas.api.types")
189def is_sparse(arr) -> bool:
190 """
191 Check whether an array-like is a 1-D pandas sparse array.
192
193 .. deprecated:: 2.1.0
194 Use isinstance(dtype, pd.SparseDtype) instead.
195
196 Check that the one-dimensional array-like is a pandas sparse array.
197 Returns True if it is a pandas sparse array, not another type of
198 sparse array.
199
200 Parameters
201 ----------
202 arr : array-like
203 Array-like to check.
204
205 Returns
206 -------
207 bool
208 Whether or not the array-like is a pandas sparse array.
209
210 See Also
211 --------
212 api.types.SparseDtype : The dtype object for pandas sparse arrays.
213
214 Examples
215 --------
216 Returns `True` if the parameter is a 1-D pandas sparse array.
217
218 >>> from pandas.api.types import is_sparse
219 >>> is_sparse(pd.arrays.SparseArray([0, 0, 1, 0]))
220 True
221 >>> is_sparse(pd.Series(pd.arrays.SparseArray([0, 0, 1, 0])))
222 True
223
224 Returns `False` if the parameter is not sparse.
225
226 >>> is_sparse(np.array([0, 0, 1, 0]))
227 False
228 >>> is_sparse(pd.Series([0, 1, 0, 0]))
229 False
230
231 Returns `False` if the parameter is not a pandas sparse array.
232
233 >>> from scipy.sparse import bsr_matrix
234 >>> is_sparse(bsr_matrix([0, 1, 0, 0]))
235 False
236
237 Returns `False` if the parameter has more than one dimension.
238 """
239 warnings.warn(
240 "is_sparse is deprecated and will be removed in a future "
241 "version. Check `isinstance(dtype, pd.SparseDtype)` instead.",
242 Pandas4Warning,
243 stacklevel=2,
244 )
245
246 dtype = getattr(arr, "dtype", arr)
247 return isinstance(dtype, SparseDtype)
248
249
250def is_scipy_sparse(arr) -> bool:
251 """
252 Check whether an array-like is a scipy.sparse.spmatrix instance.
253
254 Parameters
255 ----------
256 arr : array-like
257 The array-like to check.
258
259 Returns
260 -------
261 boolean
262 Whether or not the array-like is a scipy.sparse.spmatrix instance.
263
264 Notes
265 -----
266 If scipy is not installed, this function will always return False.
267
268 Examples
269 --------
270 >>> from scipy.sparse import bsr_matrix
271 >>> is_scipy_sparse(bsr_matrix([1, 2, 3]))
272 True
273 >>> is_scipy_sparse(pd.arrays.SparseArray([1, 2, 3]))
274 False
275 """
276 global _is_scipy_sparse
277
278 if _is_scipy_sparse is None:
279 try:
280 from scipy.sparse import issparse as _is_scipy_sparse
281 except ImportError:
282 _is_scipy_sparse = lambda _: False
283
284 assert _is_scipy_sparse is not None
285 return _is_scipy_sparse(arr)
286
287
288@set_module("pandas.api.types")
289def is_datetime64_dtype(arr_or_dtype) -> bool:
290 """
291 Check whether an array-like or dtype is of the datetime64 dtype.
292
293 Parameters
294 ----------
295 arr_or_dtype : array-like or dtype
296 The array-like or dtype to check.
297
298 Returns
299 -------
300 boolean
301 Whether or not the array-like or dtype is of the datetime64 dtype.
302
303 See Also
304 --------
305 api.types.is_datetime64_ns_dtype: Check whether the provided array or
306 dtype is of the datetime64[ns] dtype.
307 api.types.is_datetime64_any_dtype: Check whether the provided array or
308 dtype is of the datetime64 dtype.
309
310 Examples
311 --------
312 >>> from pandas.api.types import is_datetime64_dtype
313 >>> is_datetime64_dtype(object)
314 False
315 >>> is_datetime64_dtype(np.datetime64)
316 True
317 >>> is_datetime64_dtype(np.array([], dtype=int))
318 False
319 >>> is_datetime64_dtype(np.array([], dtype=np.datetime64))
320 True
321 >>> is_datetime64_dtype([1, 2, 3])
322 False
323 """
324 if isinstance(arr_or_dtype, np.dtype):
325 # GH#33400 fastpath for dtype object
326 return arr_or_dtype.kind == "M"
327 return _is_dtype_type(arr_or_dtype, classes(np.datetime64))
328
329
330@set_module("pandas.api.types")
331def is_datetime64tz_dtype(arr_or_dtype) -> bool:
332 """
333 Check whether an array-like or dtype is of a DatetimeTZDtype dtype.
334
335 .. deprecated:: 2.1.0
336 Use isinstance(dtype, pd.DatetimeTZDtype) instead.
337
338 Parameters
339 ----------
340 arr_or_dtype : array-like or dtype
341 The array-like or dtype to check.
342
343 Returns
344 -------
345 boolean
346 Whether or not the array-like or dtype is of a DatetimeTZDtype dtype.
347
348 See Also
349 --------
350 api.types.is_datetime64_dtype: Check whether an array-like or
351 dtype is of the datetime64 dtype.
352 api.types.is_datetime64_any_dtype: Check whether the provided array or
353 dtype is of the datetime64 dtype.
354
355 Examples
356 --------
357 >>> from pandas.api.types import is_datetime64tz_dtype
358 >>> is_datetime64tz_dtype(object)
359 False
360 >>> is_datetime64tz_dtype([1, 2, 3])
361 False
362 >>> is_datetime64tz_dtype(pd.DatetimeIndex([1, 2, 3])) # tz-naive
363 False
364 >>> is_datetime64tz_dtype(pd.DatetimeIndex([1, 2, 3], tz="US/Eastern"))
365 True
366
367 >>> from pandas import DatetimeTZDtype
368 >>> dtype = DatetimeTZDtype("ns", tz="US/Eastern")
369 >>> s = pd.Series([], dtype=dtype)
370 >>> is_datetime64tz_dtype(dtype)
371 True
372 >>> is_datetime64tz_dtype(s)
373 True
374 """
375 # GH#52607
376 warnings.warn(
377 "is_datetime64tz_dtype is deprecated and will be removed in a future "
378 "version. Check `isinstance(dtype, pd.DatetimeTZDtype)` instead.",
379 Pandas4Warning,
380 stacklevel=2,
381 )
382 if isinstance(arr_or_dtype, DatetimeTZDtype):
383 # GH#33400 fastpath for dtype object
384 # GH 34986
385 return True
386
387 if arr_or_dtype is None:
388 return False
389 return DatetimeTZDtype.is_dtype(arr_or_dtype)
390
391
392@set_module("pandas.api.types")
393def is_timedelta64_dtype(arr_or_dtype) -> bool:
394 """
395 Check whether an array-like or dtype is of the timedelta64 dtype.
396
397 Parameters
398 ----------
399 arr_or_dtype : array-like or dtype
400 The array-like or dtype to check.
401
402 Returns
403 -------
404 boolean
405 Whether or not the array-like or dtype is of the timedelta64 dtype.
406
407 See Also
408 --------
409 api.types.is_timedelta64_ns_dtype : Check whether the provided array or dtype is
410 of the timedelta64[ns] dtype.
411 api.types.is_period_dtype : Check whether an array-like or dtype is of the
412 Period dtype.
413
414 Examples
415 --------
416 >>> from pandas.api.types import is_timedelta64_dtype
417 >>> is_timedelta64_dtype(object)
418 False
419 >>> is_timedelta64_dtype(np.timedelta64)
420 True
421 >>> is_timedelta64_dtype([1, 2, 3])
422 False
423 >>> is_timedelta64_dtype(pd.Series([], dtype="timedelta64[ns]"))
424 True
425 >>> is_timedelta64_dtype("0 days")
426 False
427 """
428 if isinstance(arr_or_dtype, np.dtype):
429 # GH#33400 fastpath for dtype object
430 return arr_or_dtype.kind == "m"
431
432 return _is_dtype_type(arr_or_dtype, classes(np.timedelta64))
433
434
435@set_module("pandas.api.types")
436def is_period_dtype(arr_or_dtype) -> bool:
437 """
438 Check whether an array-like or dtype is of the Period dtype.
439
440 .. deprecated:: 2.2.0
441 Use isinstance(dtype, pd.PeriodDtype) instead.
442
443 Parameters
444 ----------
445 arr_or_dtype : array-like or dtype
446 The array-like or dtype to check.
447
448 Returns
449 -------
450 boolean
451 Whether or not the array-like or dtype is of the Period dtype.
452
453 See Also
454 --------
455 api.types.is_timedelta64_ns_dtype : Check whether the provided array or dtype is
456 of the timedelta64[ns] dtype.
457 api.types.is_timedelta64_dtype: Check whether an array-like or dtype
458 is of the timedelta64 dtype.
459
460 Examples
461 --------
462 >>> from pandas.api.types import is_period_dtype
463 >>> is_period_dtype(object)
464 False
465 >>> is_period_dtype(pd.PeriodDtype(freq="D"))
466 True
467 >>> is_period_dtype([1, 2, 3])
468 False
469 >>> is_period_dtype(pd.Period("2017-01-01"))
470 False
471 >>> is_period_dtype(pd.PeriodIndex([], freq="Y"))
472 True
473 """
474 warnings.warn(
475 "is_period_dtype is deprecated and will be removed in a future version. "
476 "Use `isinstance(dtype, pd.PeriodDtype)` instead",
477 Pandas4Warning,
478 stacklevel=2,
479 )
480 if isinstance(arr_or_dtype, ExtensionDtype):
481 # GH#33400 fastpath for dtype object
482 return arr_or_dtype.type is Period
483
484 if arr_or_dtype is None:
485 return False
486 return PeriodDtype.is_dtype(arr_or_dtype)
487
488
489@set_module("pandas.api.types")
490def is_interval_dtype(arr_or_dtype) -> bool:
491 """
492 Check whether an array-like or dtype is of the Interval dtype.
493
494 .. deprecated:: 2.2.0
495 Use isinstance(dtype, pd.IntervalDtype) instead.
496
497 Parameters
498 ----------
499 arr_or_dtype : array-like or dtype
500 The array-like or dtype to check.
501
502 Returns
503 -------
504 boolean
505 Whether or not the array-like or dtype is of the Interval dtype.
506
507 See Also
508 --------
509 api.types.is_object_dtype : Check whether an array-like or dtype is of the
510 object dtype.
511 api.types.is_numeric_dtype : Check whether the provided array or dtype is
512 of a numeric dtype.
513 api.types.is_categorical_dtype : Check whether an array-like or dtype is of
514 the Categorical dtype.
515
516 Examples
517 --------
518 >>> from pandas.api.types import is_interval_dtype
519 >>> is_interval_dtype(object)
520 False
521 >>> is_interval_dtype(pd.IntervalDtype())
522 True
523 >>> is_interval_dtype([1, 2, 3])
524 False
525 >>>
526 >>> interval = pd.Interval(1, 2, closed="right")
527 >>> is_interval_dtype(interval)
528 False
529 >>> is_interval_dtype(pd.IntervalIndex([interval]))
530 True
531 """
532 # GH#52607
533 warnings.warn(
534 "is_interval_dtype is deprecated and will be removed in a future version. "
535 "Use `isinstance(dtype, pd.IntervalDtype)` instead",
536 Pandas4Warning,
537 stacklevel=2,
538 )
539 if isinstance(arr_or_dtype, ExtensionDtype):
540 # GH#33400 fastpath for dtype object
541 return arr_or_dtype.type is Interval
542
543 if arr_or_dtype is None:
544 return False
545 return IntervalDtype.is_dtype(arr_or_dtype)
546
547
548@set_module("pandas.api.types")
549def is_categorical_dtype(arr_or_dtype) -> bool:
550 """
551 Check whether an array-like or dtype is of the Categorical dtype.
552
553 .. deprecated:: 2.2.0
554 Use isinstance(dtype, pd.CategoricalDtype) instead.
555
556 Parameters
557 ----------
558 arr_or_dtype : array-like or dtype
559 The array-like or dtype to check.
560
561 Returns
562 -------
563 boolean
564 Whether or not the array-like or dtype is of the Categorical dtype.
565
566 See Also
567 --------
568 api.types.is_list_like: Check if the object is list-like.
569 api.types.is_complex_dtype: Check whether the provided array or
570 dtype is of a complex dtype.
571
572 Examples
573 --------
574 >>> from pandas.api.types import is_categorical_dtype
575 >>> from pandas import CategoricalDtype
576 >>> is_categorical_dtype(object)
577 False
578 >>> is_categorical_dtype(CategoricalDtype())
579 True
580 >>> is_categorical_dtype([1, 2, 3])
581 False
582 >>> is_categorical_dtype(pd.Categorical([1, 2, 3]))
583 True
584 >>> is_categorical_dtype(pd.CategoricalIndex([1, 2, 3]))
585 True
586 """
587 # GH#52527
588 warnings.warn(
589 "is_categorical_dtype is deprecated and will be removed in a future "
590 "version. Use isinstance(dtype, pd.CategoricalDtype) instead",
591 Pandas4Warning,
592 stacklevel=2,
593 )
594 if isinstance(arr_or_dtype, ExtensionDtype):
595 # GH#33400 fastpath for dtype object
596 return arr_or_dtype.name == "category"
597
598 if arr_or_dtype is None:
599 return False
600 return CategoricalDtype.is_dtype(arr_or_dtype)
601
602
603def is_string_or_object_np_dtype(dtype: np.dtype) -> bool:
604 """
605 Faster alternative to is_string_dtype, assumes we have an np.dtype object.
606 """
607 return dtype == object or dtype.kind in "SU"
608
609
610@set_module("pandas.api.types")
611def is_string_dtype(arr_or_dtype) -> bool:
612 """
613 Check whether the provided array or dtype is of the string dtype.
614
615 If an array is passed with an object dtype, the elements must be
616 inferred as strings.
617
618 Parameters
619 ----------
620 arr_or_dtype : array-like or dtype
621 The array or dtype to check.
622
623 Returns
624 -------
625 boolean
626 Whether or not the array or dtype is of the string dtype.
627
628 See Also
629 --------
630 api.types.is_string_dtype : Check whether the provided array or dtype
631 is of the string dtype.
632
633 Examples
634 --------
635 >>> from pandas.api.types import is_string_dtype
636 >>> is_string_dtype(str)
637 True
638 >>> is_string_dtype(object)
639 True
640 >>> is_string_dtype(int)
641 False
642 >>> is_string_dtype(np.array(["a", "b"]))
643 True
644 >>> is_string_dtype(pd.Series([1, 2]))
645 False
646 >>> is_string_dtype(pd.Series([1, 2], dtype=object))
647 False
648 """
649 if hasattr(arr_or_dtype, "dtype") and _get_dtype(arr_or_dtype).kind == "O":
650 return is_all_strings(arr_or_dtype)
651
652 def condition(dtype) -> bool:
653 if is_string_or_object_np_dtype(dtype):
654 return True
655 try:
656 return dtype == "string"
657 except TypeError:
658 return False
659
660 return _is_dtype(arr_or_dtype, condition)
661
662
663@set_module("pandas.api.types")
664def is_dtype_equal(source, target) -> bool:
665 """
666 Check if two dtypes are equal.
667
668 Parameters
669 ----------
670 source : type or str
671 The first dtype to compare.
672 target : type or str
673 The second dtype to compare.
674
675 Returns
676 -------
677 boolean
678 Whether or not the two dtypes are equal.
679
680 See Also
681 --------
682 api.types.is_categorical_dtype : Check whether the provided array or dtype
683 is of the Categorical dtype.
684 api.types.is_string_dtype : Check whether the provided array or dtype
685 is of the string dtype.
686 api.types.is_object_dtype : Check whether an array-like or dtype is of the
687 object dtype.
688
689 Examples
690 --------
691 >>> from pandas.api.types import is_dtype_equal
692 >>> is_dtype_equal(int, float)
693 False
694 >>> is_dtype_equal("int", int)
695 True
696 >>> is_dtype_equal(object, "category")
697 False
698 >>> from pandas.api.types import CategoricalDtype
699 >>> is_dtype_equal(CategoricalDtype(), "category")
700 True
701 >>> from pandas.api.types import DatetimeTZDtype
702 >>> is_dtype_equal(DatetimeTZDtype(tz="UTC"), "datetime64")
703 False
704 """
705 if isinstance(target, str):
706 if not isinstance(source, str):
707 # GH#38516 ensure we get the same behavior from
708 # is_dtype_equal(CDT, "category") and CDT == "category"
709 try:
710 src = _get_dtype(source)
711 if isinstance(src, ExtensionDtype):
712 return src == target
713 except (TypeError, AttributeError, ImportError):
714 return False
715 elif isinstance(source, str):
716 return is_dtype_equal(target, source)
717
718 try:
719 source = _get_dtype(source)
720 target = _get_dtype(target)
721 return source == target
722 except (TypeError, AttributeError, ImportError):
723 # invalid comparison
724 # object == category will hit this
725 return False
726
727
728@set_module("pandas.api.types")
729def is_integer_dtype(arr_or_dtype) -> bool:
730 """
731 Check whether the provided array or dtype is of an integer dtype.
732
733 Unlike in `is_any_int_dtype`, timedelta64 instances will return False.
734
735 The nullable Integer dtypes (e.g. pandas.Int64Dtype) are also considered
736 as integer by this function.
737
738 Parameters
739 ----------
740 arr_or_dtype : array-like or dtype
741 The array or dtype to check.
742
743 Returns
744 -------
745 boolean
746 Whether or not the array or dtype is of an integer dtype and
747 not an instance of timedelta64.
748
749 See Also
750 --------
751 api.types.is_integer : Return True if given object is integer.
752 api.types.is_numeric_dtype : Check whether the provided array or dtype is of a
753 numeric dtype.
754 api.types.is_float_dtype : Check whether the provided array or dtype is of a
755 float dtype.
756 Int64Dtype : An ExtensionDtype for Int64Dtype integer data.
757
758 Examples
759 --------
760 >>> from pandas.api.types import is_integer_dtype
761 >>> is_integer_dtype(str)
762 False
763 >>> is_integer_dtype(int)
764 True
765 >>> is_integer_dtype(float)
766 False
767 >>> is_integer_dtype(np.uint64)
768 True
769 >>> is_integer_dtype("int8")
770 True
771 >>> is_integer_dtype("Int8")
772 True
773 >>> is_integer_dtype(pd.Int8Dtype)
774 True
775 >>> is_integer_dtype(np.datetime64)
776 False
777 >>> is_integer_dtype(np.timedelta64)
778 False
779 >>> is_integer_dtype(np.array(["a", "b"]))
780 False
781 >>> is_integer_dtype(pd.Series([1, 2]))
782 True
783 >>> is_integer_dtype(np.array([], dtype="m8[ns]"))
784 False
785 >>> is_integer_dtype(pd.Index([1, 2.0])) # float
786 False
787 """
788 return _is_dtype_type(
789 arr_or_dtype, _classes_and_not_datetimelike(np.integer)
790 ) or _is_dtype(
791 arr_or_dtype, lambda typ: isinstance(typ, ExtensionDtype) and typ.kind in "iu"
792 )
793
794
795@set_module("pandas.api.types")
796def is_signed_integer_dtype(arr_or_dtype) -> bool:
797 """
798 Check whether the provided array or dtype is of a signed integer dtype.
799
800 Unlike in `is_any_int_dtype`, timedelta64 instances will return False.
801
802 The nullable Integer dtypes (e.g. pandas.Int64Dtype) are also considered
803 as integer by this function.
804
805 Parameters
806 ----------
807 arr_or_dtype : array-like or dtype
808 The array or dtype to check.
809
810 Returns
811 -------
812 boolean
813 Whether or not the array or dtype is of a signed integer dtype
814 and not an instance of timedelta64.
815
816 See Also
817 --------
818 api.types.is_integer_dtype: Check whether the provided array or dtype
819 is of an integer dtype.
820 api.types.is_numeric_dtype: Check whether the provided array or dtype
821 is of a numeric dtype.
822 api.types.is_unsigned_integer_dtype: Check whether the provided array
823 or dtype is of an unsigned integer dtype.
824
825 Examples
826 --------
827 >>> from pandas.api.types import is_signed_integer_dtype
828 >>> is_signed_integer_dtype(str)
829 False
830 >>> is_signed_integer_dtype(int)
831 True
832 >>> is_signed_integer_dtype(float)
833 False
834 >>> is_signed_integer_dtype(np.uint64) # unsigned
835 False
836 >>> is_signed_integer_dtype("int8")
837 True
838 >>> is_signed_integer_dtype("Int8")
839 True
840 >>> is_signed_integer_dtype(pd.Int8Dtype)
841 True
842 >>> is_signed_integer_dtype(np.datetime64)
843 False
844 >>> is_signed_integer_dtype(np.timedelta64)
845 False
846 >>> is_signed_integer_dtype(np.array(["a", "b"]))
847 False
848 >>> is_signed_integer_dtype(pd.Series([1, 2]))
849 True
850 >>> is_signed_integer_dtype(np.array([], dtype="m8[ns]"))
851 False
852 >>> is_signed_integer_dtype(pd.Index([1, 2.0])) # float
853 False
854 >>> is_signed_integer_dtype(np.array([1, 2], dtype=np.uint32)) # unsigned
855 False
856 """
857 return _is_dtype_type(
858 arr_or_dtype, _classes_and_not_datetimelike(np.signedinteger)
859 ) or _is_dtype(
860 arr_or_dtype, lambda typ: isinstance(typ, ExtensionDtype) and typ.kind == "i"
861 )
862
863
864@set_module("pandas.api.types")
865def is_unsigned_integer_dtype(arr_or_dtype) -> bool:
866 """
867 Check whether the provided array or dtype is of an unsigned integer dtype.
868
869 The nullable Integer dtypes (e.g. pandas.UInt64Dtype) are also
870 considered as integer by this function.
871
872 Parameters
873 ----------
874 arr_or_dtype : array-like or dtype
875 The array or dtype to check.
876
877 Returns
878 -------
879 boolean
880 Whether or not the array or dtype is of an unsigned integer dtype.
881
882 See Also
883 --------
884 api.types.is_signed_integer_dtype : Check whether the provided array
885 or dtype is of a signed integer dtype.
886 api.types.is_integer_dtype : Check whether the provided array or dtype
887 is of an integer dtype.
888 api.types.is_numeric_dtype : Check whether the provided array or dtype
889 is of a numeric dtype.
890
891 Examples
892 --------
893 >>> from pandas.api.types import is_unsigned_integer_dtype
894 >>> is_unsigned_integer_dtype(str)
895 False
896 >>> is_unsigned_integer_dtype(int) # signed
897 False
898 >>> is_unsigned_integer_dtype(float)
899 False
900 >>> is_unsigned_integer_dtype(np.uint64)
901 True
902 >>> is_unsigned_integer_dtype("uint8")
903 True
904 >>> is_unsigned_integer_dtype("UInt8")
905 True
906 >>> is_unsigned_integer_dtype(pd.UInt8Dtype)
907 True
908 >>> is_unsigned_integer_dtype(np.array(["a", "b"]))
909 False
910 >>> is_unsigned_integer_dtype(pd.Series([1, 2])) # signed
911 False
912 >>> is_unsigned_integer_dtype(pd.Index([1, 2.0])) # float
913 False
914 >>> is_unsigned_integer_dtype(np.array([1, 2], dtype=np.uint32))
915 True
916 """
917 return _is_dtype_type(
918 arr_or_dtype, _classes_and_not_datetimelike(np.unsignedinteger)
919 ) or _is_dtype(
920 arr_or_dtype, lambda typ: isinstance(typ, ExtensionDtype) and typ.kind == "u"
921 )
922
923
924@set_module("pandas.api.types")
925def is_int64_dtype(arr_or_dtype) -> bool:
926 """
927 Check whether the provided array or dtype is of the int64 dtype.
928
929 .. deprecated:: 2.1.0
930
931 is_int64_dtype is deprecated and will be removed in a future
932 version. Use dtype == np.int64 instead.
933
934 Parameters
935 ----------
936 arr_or_dtype : array-like or dtype
937 The array or dtype to check.
938
939 Returns
940 -------
941 boolean
942 Whether or not the array or dtype is of the int64 dtype.
943
944 See Also
945 --------
946 api.types.is_float_dtype : Check whether the provided array or dtype is of a
947 float dtype.
948 api.types.is_bool_dtype : Check whether the provided array or dtype is of a
949 boolean dtype.
950 api.types.is_object_dtype : Check whether an array-like or dtype is of the
951 object dtype.
952 numpy.int64 : Numpy's 64-bit integer type.
953
954 Notes
955 -----
956 Depending on system architecture, the return value of `is_int64_dtype(
957 int)` will be True if the OS uses 64-bit integers and False if the OS
958 uses 32-bit integers.
959
960 Examples
961 --------
962 >>> from pandas.api.types import is_int64_dtype
963 >>> is_int64_dtype(str) # doctest: +SKIP
964 False
965 >>> is_int64_dtype(np.int32) # doctest: +SKIP
966 False
967 >>> is_int64_dtype(np.int64) # doctest: +SKIP
968 True
969 >>> is_int64_dtype("int8") # doctest: +SKIP
970 False
971 >>> is_int64_dtype("Int8") # doctest: +SKIP
972 False
973 >>> is_int64_dtype(pd.Int64Dtype) # doctest: +SKIP
974 True
975 >>> is_int64_dtype(float) # doctest: +SKIP
976 False
977 >>> is_int64_dtype(np.uint64) # unsigned # doctest: +SKIP
978 False
979 >>> is_int64_dtype(np.array(["a", "b"])) # doctest: +SKIP
980 False
981 >>> is_int64_dtype(np.array([1, 2], dtype=np.int64)) # doctest: +SKIP
982 True
983 >>> is_int64_dtype(pd.Index([1, 2.0])) # float # doctest: +SKIP
984 False
985 >>> is_int64_dtype(np.array([1, 2], dtype=np.uint32)) # unsigned # doctest: +SKIP
986 False
987 """
988 # GH#52564
989 warnings.warn(
990 "is_int64_dtype is deprecated and will be removed in a future "
991 "version. Use dtype == np.int64 instead.",
992 Pandas4Warning,
993 stacklevel=2,
994 )
995 return _is_dtype_type(arr_or_dtype, classes(np.int64))
996
997
998@set_module("pandas.api.types")
999def is_datetime64_any_dtype(arr_or_dtype) -> bool:
1000 """
1001 Check whether the provided array or dtype is of the datetime64 dtype.
1002
1003 Parameters
1004 ----------
1005 arr_or_dtype : array-like or dtype
1006 The array or dtype to check.
1007
1008 Returns
1009 -------
1010 bool
1011 Whether or not the array or dtype is of the datetime64 dtype.
1012
1013 See Also
1014 --------
1015 api.types.is_datetime64_dtype : Check whether an array-like or dtype is of the
1016 datetime64 dtype.
1017 api.is_datetime64_ns_dtype : Check whether the provided array or dtype is of the
1018 datetime64[ns] dtype.
1019 api.is_datetime64tz_dtype : Check whether an array-like or dtype is of a
1020 DatetimeTZDtype dtype.
1021
1022 Examples
1023 --------
1024 >>> from pandas.api.types import is_datetime64_any_dtype
1025 >>> from pandas.api.types import DatetimeTZDtype
1026 >>> is_datetime64_any_dtype(str)
1027 False
1028 >>> is_datetime64_any_dtype(int)
1029 False
1030 >>> is_datetime64_any_dtype(np.datetime64) # can be tz-naive
1031 True
1032 >>> is_datetime64_any_dtype(DatetimeTZDtype("ns", "US/Eastern"))
1033 True
1034 >>> is_datetime64_any_dtype(np.array(["a", "b"]))
1035 False
1036 >>> is_datetime64_any_dtype(np.array([1, 2]))
1037 False
1038 >>> is_datetime64_any_dtype(np.array([], dtype="datetime64[ns]"))
1039 True
1040 >>> is_datetime64_any_dtype(pd.DatetimeIndex([1, 2, 3], dtype="datetime64[ns]"))
1041 True
1042 """
1043 if isinstance(arr_or_dtype, (np.dtype, ExtensionDtype)):
1044 # GH#33400 fastpath for dtype object
1045 return arr_or_dtype.kind == "M"
1046
1047 if arr_or_dtype is None:
1048 return False
1049
1050 try:
1051 tipo = _get_dtype(arr_or_dtype)
1052 except TypeError:
1053 return False
1054 return (
1055 lib.is_np_dtype(tipo, "M")
1056 or isinstance(tipo, DatetimeTZDtype)
1057 or (isinstance(tipo, ExtensionDtype) and tipo.kind == "M")
1058 )
1059
1060
1061@set_module("pandas.api.types")
1062def is_datetime64_ns_dtype(arr_or_dtype) -> bool:
1063 """
1064 Check whether the provided array or dtype is of the datetime64[ns] dtype.
1065
1066 Parameters
1067 ----------
1068 arr_or_dtype : array-like or dtype
1069 The array or dtype to check.
1070
1071 Returns
1072 -------
1073 bool
1074 Whether or not the array or dtype is of the datetime64[ns] dtype.
1075
1076 See Also
1077 --------
1078 api.types.is_datetime64_dtype: Check whether an array-like or
1079 dtype is of the datetime64 dtype.
1080 api.types.is_datetime64_any_dtype: Check whether the provided array or
1081 dtype is of the datetime64 dtype.
1082
1083 Examples
1084 --------
1085 >>> from pandas.api.types import is_datetime64_ns_dtype
1086 >>> from pandas.api.types import DatetimeTZDtype
1087 >>> is_datetime64_ns_dtype(str)
1088 False
1089 >>> is_datetime64_ns_dtype(int)
1090 False
1091 >>> is_datetime64_ns_dtype(np.datetime64) # no unit
1092 False
1093 >>> is_datetime64_ns_dtype(DatetimeTZDtype("ns", "US/Eastern"))
1094 True
1095 >>> is_datetime64_ns_dtype(np.array(["a", "b"]))
1096 False
1097 >>> is_datetime64_ns_dtype(np.array([1, 2]))
1098 False
1099 >>> is_datetime64_ns_dtype(np.array([], dtype="datetime64")) # no unit
1100 False
1101 >>> is_datetime64_ns_dtype(np.array([], dtype="datetime64[ps]")) # wrong unit
1102 False
1103 >>> is_datetime64_ns_dtype(pd.DatetimeIndex([1, 2, 3], dtype="datetime64[ns]"))
1104 True
1105 """
1106 if arr_or_dtype is None:
1107 return False
1108 try:
1109 tipo = _get_dtype(arr_or_dtype)
1110 except TypeError:
1111 return False
1112 return tipo == DT64NS_DTYPE or (
1113 isinstance(tipo, DatetimeTZDtype) and tipo.unit == "ns"
1114 )
1115
1116
1117@set_module("pandas.api.types")
1118def is_timedelta64_ns_dtype(arr_or_dtype) -> bool:
1119 """
1120 Check whether the provided array or dtype is of the timedelta64[ns] dtype.
1121
1122 This is a very specific dtype, so generic ones like `np.timedelta64`
1123 will return False if passed into this function.
1124
1125 Parameters
1126 ----------
1127 arr_or_dtype : array-like or dtype
1128 The array or dtype to check.
1129
1130 Returns
1131 -------
1132 boolean
1133 Whether or not the array or dtype is of the timedelta64[ns] dtype.
1134
1135 See Also
1136 --------
1137 api.types.is_timedelta64_dtype: Check whether an array-like or dtype
1138 is of the timedelta64 dtype.
1139
1140 Examples
1141 --------
1142 >>> from pandas.api.types import is_timedelta64_ns_dtype
1143 >>> is_timedelta64_ns_dtype(np.dtype("m8[ns]"))
1144 True
1145 >>> is_timedelta64_ns_dtype(np.dtype("m8[ps]")) # Wrong frequency
1146 False
1147 >>> is_timedelta64_ns_dtype(np.array([1, 2], dtype="m8[ns]"))
1148 True
1149 >>> is_timedelta64_ns_dtype(np.array([1, 2], dtype="m8"))
1150 False
1151 """
1152 return _is_dtype(arr_or_dtype, lambda dtype: dtype == TD64NS_DTYPE)
1153
1154
1155# This exists to silence numpy deprecation warnings, see GH#29553
1156def is_numeric_v_string_like(a: ArrayLike, b) -> bool:
1157 """
1158 Check if we are comparing a string-like object to a numeric ndarray.
1159 NumPy doesn't like to compare such objects, especially numeric arrays
1160 and scalar string-likes.
1161
1162 Parameters
1163 ----------
1164 a : array-like, scalar
1165 The first object to check.
1166 b : array-like, scalar
1167 The second object to check.
1168
1169 Returns
1170 -------
1171 boolean
1172 Whether we return a comparing a string-like object to a numeric array.
1173
1174 Examples
1175 --------
1176 >>> is_numeric_v_string_like(np.array([1]), "foo")
1177 True
1178 >>> is_numeric_v_string_like(np.array([1, 2]), np.array(["foo"]))
1179 True
1180 >>> is_numeric_v_string_like(np.array(["foo"]), np.array([1, 2]))
1181 True
1182 >>> is_numeric_v_string_like(np.array([1]), np.array([2]))
1183 False
1184 >>> is_numeric_v_string_like(np.array(["foo"]), np.array(["foo"]))
1185 False
1186 """
1187 is_a_array = isinstance(a, np.ndarray)
1188 is_b_array = isinstance(b, np.ndarray)
1189
1190 is_a_numeric_array = is_a_array and a.dtype.kind in "uifcb"
1191 is_b_numeric_array = is_b_array and b.dtype.kind in "uifcb"
1192 is_a_string_array = is_a_array and a.dtype.kind in "SU"
1193 is_b_string_array = is_b_array and b.dtype.kind in "SU"
1194
1195 is_b_scalar_string_like = not is_b_array and isinstance(b, str)
1196
1197 return (
1198 (is_a_numeric_array and is_b_scalar_string_like)
1199 or (is_a_numeric_array and is_b_string_array)
1200 or (is_b_numeric_array and is_a_string_array)
1201 )
1202
1203
1204def needs_i8_conversion(dtype: DtypeObj | None) -> bool:
1205 """
1206 Check whether the dtype should be converted to int64.
1207
1208 Dtype "needs" such a conversion if the dtype is of a datetime-like dtype
1209
1210 Parameters
1211 ----------
1212 dtype : np.dtype, ExtensionDtype, or None
1213
1214 Returns
1215 -------
1216 boolean
1217 Whether or not the dtype should be converted to int64.
1218
1219 Examples
1220 --------
1221 >>> needs_i8_conversion(str)
1222 False
1223 >>> needs_i8_conversion(np.int64)
1224 False
1225 >>> needs_i8_conversion(np.datetime64)
1226 False
1227 >>> needs_i8_conversion(np.dtype(np.datetime64))
1228 True
1229 >>> needs_i8_conversion(np.array(["a", "b"]))
1230 False
1231 >>> needs_i8_conversion(pd.Series([1, 2]))
1232 False
1233 >>> needs_i8_conversion(pd.Series([], dtype="timedelta64[ns]"))
1234 False
1235 >>> needs_i8_conversion(pd.DatetimeIndex([1, 2, 3], tz="US/Eastern"))
1236 False
1237 >>> needs_i8_conversion(pd.DatetimeIndex([1, 2, 3], tz="US/Eastern").dtype)
1238 True
1239 """
1240 if isinstance(dtype, np.dtype):
1241 return dtype.kind in "mM"
1242 return isinstance(dtype, (PeriodDtype, DatetimeTZDtype))
1243
1244
1245@set_module("pandas.api.types")
1246def is_numeric_dtype(arr_or_dtype) -> bool:
1247 """
1248 Check whether the provided array or dtype is of a numeric dtype.
1249
1250 Parameters
1251 ----------
1252 arr_or_dtype : array-like or dtype
1253 The array or dtype to check.
1254
1255 Returns
1256 -------
1257 boolean
1258 Whether or not the array or dtype is of a numeric dtype.
1259
1260 See Also
1261 --------
1262 api.types.is_integer_dtype: Check whether the provided array or dtype
1263 is of an integer dtype.
1264 api.types.is_unsigned_integer_dtype: Check whether the provided array
1265 or dtype is of an unsigned integer dtype.
1266 api.types.is_signed_integer_dtype: Check whether the provided array
1267 or dtype is of a signed integer dtype.
1268
1269 Examples
1270 --------
1271 >>> from pandas.api.types import is_numeric_dtype
1272 >>> is_numeric_dtype(str)
1273 False
1274 >>> is_numeric_dtype(int)
1275 True
1276 >>> is_numeric_dtype(float)
1277 True
1278 >>> is_numeric_dtype(np.uint64)
1279 True
1280 >>> is_numeric_dtype(np.datetime64)
1281 False
1282 >>> is_numeric_dtype(np.timedelta64)
1283 False
1284 >>> is_numeric_dtype(np.array(["a", "b"]))
1285 False
1286 >>> is_numeric_dtype(pd.Series([1, 2]))
1287 True
1288 >>> is_numeric_dtype(pd.Index([1, 2.0]))
1289 True
1290 >>> is_numeric_dtype(np.array([], dtype="m8[ns]"))
1291 False
1292 """
1293 return _is_dtype_type(
1294 arr_or_dtype, _classes_and_not_datetimelike(np.number, np.bool_)
1295 ) or _is_dtype(
1296 arr_or_dtype, lambda typ: isinstance(typ, ExtensionDtype) and typ._is_numeric
1297 )
1298
1299
1300@set_module("pandas.api.types")
1301def is_any_real_numeric_dtype(arr_or_dtype) -> bool:
1302 """
1303 Check whether the provided array or dtype is of a real number dtype.
1304
1305 Parameters
1306 ----------
1307 arr_or_dtype : array-like or dtype
1308 The array or dtype to check.
1309
1310 Returns
1311 -------
1312 boolean
1313 Whether or not the array or dtype is of a real number dtype.
1314
1315 See Also
1316 --------
1317 is_numeric_dtype : Check if a dtype is numeric.
1318 is_complex_dtype : Check if a dtype is complex.
1319 is_bool_dtype : Check if a dtype is boolean.
1320
1321 Examples
1322 --------
1323 >>> from pandas.api.types import is_any_real_numeric_dtype
1324 >>> is_any_real_numeric_dtype(int)
1325 True
1326 >>> is_any_real_numeric_dtype(float)
1327 True
1328 >>> is_any_real_numeric_dtype(object)
1329 False
1330 >>> is_any_real_numeric_dtype(str)
1331 False
1332 >>> is_any_real_numeric_dtype(complex(1, 2))
1333 False
1334 >>> is_any_real_numeric_dtype(bool)
1335 False
1336 """
1337 return (
1338 is_numeric_dtype(arr_or_dtype)
1339 and not is_complex_dtype(arr_or_dtype)
1340 and not is_bool_dtype(arr_or_dtype)
1341 )
1342
1343
1344@set_module("pandas.api.types")
1345def is_float_dtype(arr_or_dtype) -> bool:
1346 """
1347 Check whether the provided array or dtype is of a float dtype.
1348
1349 The function checks for floating-point data types, which represent real numbers
1350 that may have fractional components.
1351
1352 Parameters
1353 ----------
1354 arr_or_dtype : array-like or dtype
1355 The array or dtype to check.
1356
1357 Returns
1358 -------
1359 boolean
1360 Whether or not the array or dtype is of a float dtype.
1361
1362 See Also
1363 --------
1364 api.types.is_numeric_dtype : Check whether the provided array or dtype is of
1365 a numeric dtype.
1366 api.types.is_integer_dtype : Check whether the provided array or dtype is of
1367 an integer dtype.
1368 api.types.is_object_dtype : Check whether an array-like or dtype is of the
1369 object dtype.
1370
1371 Examples
1372 --------
1373 >>> from pandas.api.types import is_float_dtype
1374 >>> is_float_dtype(str)
1375 False
1376 >>> is_float_dtype(int)
1377 False
1378 >>> is_float_dtype(float)
1379 True
1380 >>> is_float_dtype(np.array(["a", "b"]))
1381 False
1382 >>> is_float_dtype(pd.Series([1, 2]))
1383 False
1384 >>> is_float_dtype(pd.Index([1, 2.0]))
1385 True
1386 """
1387 return _is_dtype_type(arr_or_dtype, classes(np.floating)) or _is_dtype(
1388 arr_or_dtype, lambda typ: isinstance(typ, ExtensionDtype) and typ.kind in "f"
1389 )
1390
1391
1392@set_module("pandas.api.types")
1393def is_bool_dtype(arr_or_dtype) -> bool:
1394 """
1395 Check whether the provided array or dtype is of a boolean dtype.
1396
1397 This function verifies whether a given object is a boolean data type. The input
1398 can be an array or a dtype object. Accepted array types include instances
1399 of ``np.array``, ``pd.Series``, ``pd.Index``, and similar array-like structures.
1400
1401 Parameters
1402 ----------
1403 arr_or_dtype : array-like or dtype
1404 The array or dtype to check.
1405
1406 Returns
1407 -------
1408 boolean
1409 Whether or not the array or dtype is of a boolean dtype.
1410
1411 See Also
1412 --------
1413 api.types.is_bool : Check if an object is a boolean.
1414
1415 Notes
1416 -----
1417 An ExtensionArray is considered boolean when the ``_is_boolean``
1418 attribute is set to True.
1419
1420 Examples
1421 --------
1422 >>> from pandas.api.types import is_bool_dtype
1423 >>> is_bool_dtype(str)
1424 False
1425 >>> is_bool_dtype(int)
1426 False
1427 >>> is_bool_dtype(bool)
1428 True
1429 >>> is_bool_dtype(np.bool_)
1430 True
1431 >>> is_bool_dtype(np.array(["a", "b"]))
1432 False
1433 >>> is_bool_dtype(pd.Series([1, 2]))
1434 False
1435 >>> is_bool_dtype(np.array([True, False]))
1436 True
1437 >>> is_bool_dtype(pd.Categorical([True, False]))
1438 True
1439 >>> is_bool_dtype(pd.arrays.SparseArray([True, False]))
1440 True
1441 """
1442 if arr_or_dtype is None:
1443 return False
1444 try:
1445 dtype = _get_dtype(arr_or_dtype)
1446 except (TypeError, ValueError):
1447 return False
1448
1449 if isinstance(dtype, CategoricalDtype):
1450 arr_or_dtype = dtype.categories
1451 # now we use the special definition for Index
1452
1453 if isinstance(arr_or_dtype, ABCIndex):
1454 # Allow Index[object] that is all-bools or Index["boolean"]
1455 if arr_or_dtype.inferred_type == "boolean":
1456 if not is_bool_dtype(arr_or_dtype.dtype):
1457 # GH#52680
1458 warnings.warn(
1459 "The behavior of is_bool_dtype with an object-dtype Index "
1460 "of bool objects is deprecated. In a future version, "
1461 "this will return False. Cast the Index to a bool dtype instead.",
1462 Pandas4Warning,
1463 stacklevel=2,
1464 )
1465 return True
1466 return False
1467 elif isinstance(dtype, ExtensionDtype):
1468 return getattr(dtype, "_is_boolean", False)
1469
1470 return issubclass(dtype.type, np.bool_)
1471
1472
1473def is_1d_only_ea_dtype(dtype: DtypeObj | None) -> bool:
1474 """
1475 Analogue to is_extension_array_dtype but excluding DatetimeTZDtype.
1476 """
1477 return isinstance(dtype, ExtensionDtype) and not dtype._supports_2d
1478
1479
1480@set_module("pandas.api.types")
1481def is_extension_array_dtype(arr_or_dtype) -> bool:
1482 """
1483 Check if an object is a pandas extension array type.
1484
1485 See the :ref:`Use Guide <extending.extension-types>` for more.
1486
1487 Parameters
1488 ----------
1489 arr_or_dtype : object
1490 For array-like input, the ``.dtype`` attribute will
1491 be extracted.
1492
1493 Returns
1494 -------
1495 bool
1496 Whether the `arr_or_dtype` is an extension array type.
1497
1498 See Also
1499 --------
1500 api.extensions.ExtensionArray : Abstract base class for pandas extension arrays.
1501
1502 Notes
1503 -----
1504 This checks whether an object implements the pandas extension
1505 array interface. In pandas, this includes:
1506
1507 * Categorical
1508 * Sparse
1509 * Interval
1510 * Period
1511 * DatetimeArray
1512 * TimedeltaArray
1513
1514 Third-party libraries may implement arrays or types satisfying
1515 this interface as well.
1516
1517 Examples
1518 --------
1519 >>> from pandas.api.types import is_extension_array_dtype
1520 >>> arr = pd.Categorical(["a", "b"])
1521 >>> is_extension_array_dtype(arr)
1522 True
1523 >>> is_extension_array_dtype(arr.dtype)
1524 True
1525
1526 >>> arr = np.array(["a", "b"])
1527 >>> is_extension_array_dtype(arr.dtype)
1528 False
1529 """
1530 dtype = getattr(arr_or_dtype, "dtype", arr_or_dtype)
1531 if isinstance(dtype, ExtensionDtype):
1532 return True
1533 elif isinstance(dtype, np.dtype):
1534 return False
1535 else:
1536 try:
1537 with warnings.catch_warnings():
1538 # pandas_dtype(..) can raise UserWarning for class input
1539 warnings.simplefilter("ignore", UserWarning)
1540 dtype = pandas_dtype(dtype)
1541 except (TypeError, ValueError):
1542 # np.dtype(..) can raise ValueError
1543 return False
1544 return isinstance(dtype, ExtensionDtype)
1545
1546
1547def is_ea_or_datetimelike_dtype(dtype: DtypeObj | None) -> bool:
1548 """
1549 Check for ExtensionDtype, datetime64 dtype, or timedelta64 dtype.
1550
1551 Notes
1552 -----
1553 Checks only for dtype objects, not dtype-castable strings or types.
1554 """
1555 return isinstance(dtype, ExtensionDtype) or (lib.is_np_dtype(dtype, "mM"))
1556
1557
1558@set_module("pandas.api.types")
1559def is_complex_dtype(arr_or_dtype) -> bool:
1560 """
1561 Check whether the provided array or dtype is of a complex dtype.
1562
1563 Parameters
1564 ----------
1565 arr_or_dtype : array-like or dtype
1566 The array or dtype to check.
1567
1568 Returns
1569 -------
1570 boolean
1571 Whether or not the array or dtype is of a complex dtype.
1572
1573 See Also
1574 --------
1575 api.types.is_complex: Return True if given object is complex.
1576 api.types.is_numeric_dtype: Check whether the provided array or
1577 dtype is of a numeric dtype.
1578 api.types.is_integer_dtype: Check whether the provided array or
1579 dtype is of an integer dtype.
1580
1581 Examples
1582 --------
1583 >>> from pandas.api.types import is_complex_dtype
1584 >>> is_complex_dtype(str)
1585 False
1586 >>> is_complex_dtype(int)
1587 False
1588 >>> is_complex_dtype(np.complex128)
1589 True
1590 >>> is_complex_dtype(np.array(["a", "b"]))
1591 False
1592 >>> is_complex_dtype(pd.Series([1, 2]))
1593 False
1594 >>> is_complex_dtype(np.array([1 + 1j, 5]))
1595 True
1596 """
1597 return _is_dtype_type(arr_or_dtype, classes(np.complexfloating))
1598
1599
1600def _is_dtype(arr_or_dtype, condition) -> bool:
1601 """
1602 Return true if the condition is satisfied for the arr_or_dtype.
1603
1604 Parameters
1605 ----------
1606 arr_or_dtype : array-like, str, np.dtype, or ExtensionArrayType
1607 The array-like or dtype object whose dtype we want to extract.
1608 condition : callable[Union[np.dtype, ExtensionDtype]]
1609
1610 Returns
1611 -------
1612 bool
1613
1614 """
1615 if arr_or_dtype is None:
1616 return False
1617 try:
1618 dtype = _get_dtype(arr_or_dtype)
1619 except (TypeError, ValueError):
1620 return False
1621 return condition(dtype)
1622
1623
1624def _get_dtype(arr_or_dtype) -> DtypeObj:
1625 """
1626 Get the dtype instance associated with an array
1627 or dtype object.
1628
1629 Parameters
1630 ----------
1631 arr_or_dtype : array-like or dtype
1632 The array-like or dtype object whose dtype we want to extract.
1633
1634 Returns
1635 -------
1636 obj_dtype : The extract dtype instance from the
1637 passed in array or dtype object.
1638
1639 Raises
1640 ------
1641 TypeError : The passed in object is None.
1642 """
1643 if arr_or_dtype is None:
1644 raise TypeError("Cannot deduce dtype from null object")
1645
1646 # fastpath
1647 if isinstance(arr_or_dtype, np.dtype):
1648 return arr_or_dtype
1649 elif isinstance(arr_or_dtype, type):
1650 return np.dtype(arr_or_dtype)
1651
1652 # if we have an array-like
1653 elif hasattr(arr_or_dtype, "dtype"):
1654 arr_or_dtype = arr_or_dtype.dtype
1655
1656 return pandas_dtype(arr_or_dtype)
1657
1658
1659def _is_dtype_type(arr_or_dtype, condition) -> bool:
1660 """
1661 Return true if the condition is satisfied for the arr_or_dtype.
1662
1663 Parameters
1664 ----------
1665 arr_or_dtype : array-like or dtype
1666 The array-like or dtype object whose dtype we want to extract.
1667 condition : callable[Union[np.dtype, ExtensionDtypeType]]
1668
1669 Returns
1670 -------
1671 bool : if the condition is satisfied for the arr_or_dtype
1672 """
1673 if arr_or_dtype is None:
1674 return condition(type(None))
1675
1676 # fastpath
1677 if isinstance(arr_or_dtype, np.dtype):
1678 return condition(arr_or_dtype.type)
1679 elif isinstance(arr_or_dtype, type):
1680 if issubclass(arr_or_dtype, ExtensionDtype):
1681 arr_or_dtype = arr_or_dtype.type
1682 return condition(np.dtype(arr_or_dtype).type)
1683
1684 # if we have an array-like
1685 if hasattr(arr_or_dtype, "dtype"):
1686 arr_or_dtype = arr_or_dtype.dtype
1687
1688 # we are not possibly a dtype
1689 elif is_list_like(arr_or_dtype):
1690 return condition(type(None))
1691
1692 try:
1693 tipo = pandas_dtype(arr_or_dtype).type
1694 except (TypeError, ValueError):
1695 if is_scalar(arr_or_dtype):
1696 return condition(type(None))
1697
1698 return False
1699
1700 return condition(tipo)
1701
1702
1703def infer_dtype_from_object(dtype) -> type:
1704 """
1705 Get a numpy dtype.type-style object for a dtype object.
1706
1707 This methods also includes handling of the datetime64[ns] and
1708 datetime64[ns, TZ] objects.
1709
1710 If no dtype can be found, we return ``object``.
1711
1712 Parameters
1713 ----------
1714 dtype : dtype, type
1715 The dtype object whose numpy dtype.type-style
1716 object we want to extract.
1717
1718 Returns
1719 -------
1720 type
1721 """
1722 if isinstance(dtype, type) and issubclass(dtype, np.generic):
1723 # Type object from a dtype
1724
1725 return dtype
1726 elif isinstance(dtype, (np.dtype, ExtensionDtype)):
1727 # dtype object
1728 try:
1729 _validate_date_like_dtype(dtype)
1730 except TypeError:
1731 # Should still pass if we don't have a date-like
1732 pass
1733 if hasattr(dtype, "numpy_dtype"):
1734 # TODO: Implement this properly
1735 # https://github.com/pandas-dev/pandas/issues/52576
1736 return dtype.numpy_dtype.type
1737 return dtype.type
1738
1739 try:
1740 dtype = pandas_dtype(dtype)
1741 except TypeError:
1742 pass
1743
1744 if isinstance(dtype, ExtensionDtype):
1745 return dtype.type
1746 elif isinstance(dtype, str):
1747 # TODO(jreback)
1748 # should deprecate these
1749 if dtype in ["datetimetz", "datetime64tz"]:
1750 return DatetimeTZDtype.type
1751 elif dtype in ["period"]:
1752 raise NotImplementedError
1753
1754 if dtype in ["datetime", "timedelta"]:
1755 dtype += "64"
1756 try:
1757 return infer_dtype_from_object(getattr(np, dtype))
1758 except (AttributeError, TypeError):
1759 # Handles cases like _get_dtype(int) i.e.,
1760 # Python objects that are valid dtypes
1761 # (unlike user-defined types, in general)
1762 #
1763 # TypeError handles the float16 type code of 'e'
1764 # further handle internal types
1765 pass
1766
1767 return infer_dtype_from_object(np.dtype(dtype))
1768
1769
1770def _validate_date_like_dtype(dtype) -> None:
1771 """
1772 Check whether the dtype is a date-like dtype. Raises an error if invalid.
1773
1774 Parameters
1775 ----------
1776 dtype : dtype, type
1777 The dtype to check.
1778
1779 Raises
1780 ------
1781 TypeError : The dtype could not be casted to a date-like dtype.
1782 ValueError : The dtype is an illegal date-like dtype (e.g. the
1783 frequency provided is too specific)
1784 """
1785 try:
1786 typ = np.datetime_data(dtype)[0]
1787 except ValueError as e:
1788 raise TypeError(e) from e
1789 if typ not in ["generic", "ns"]:
1790 raise ValueError(
1791 f"{dtype.name!r} is too specific of a frequency, "
1792 f"try passing {dtype.type.__name__!r}"
1793 )
1794
1795
1796def validate_all_hashable(*args, error_name: str | None = None) -> None:
1797 """
1798 Return None if all args are hashable, else raise a TypeError.
1799
1800 Parameters
1801 ----------
1802 *args
1803 Arguments to validate.
1804 error_name : str, optional
1805 The name to use if error
1806
1807 Raises
1808 ------
1809 TypeError : If an argument is not hashable
1810
1811 Returns
1812 -------
1813 None
1814 """
1815 if not all(is_hashable(arg) for arg in args):
1816 if error_name:
1817 raise TypeError(f"{error_name} must be a hashable type")
1818 raise TypeError("All elements must be hashable")
1819
1820
1821@set_module("pandas.api.types")
1822def pandas_dtype(dtype) -> DtypeObj:
1823 """
1824 Convert input into a pandas only dtype object or a numpy dtype object.
1825
1826 Parameters
1827 ----------
1828 dtype : object
1829 The object to be converted into a dtype.
1830
1831 Returns
1832 -------
1833 np.dtype or a pandas dtype
1834 The converted dtype, which can be either a numpy dtype or a pandas dtype.
1835
1836 Raises
1837 ------
1838 TypeError if not a dtype
1839
1840 See Also
1841 --------
1842 api.types.is_dtype : Return true if the condition is satisfied for the arr_or_dtype.
1843
1844 Examples
1845 --------
1846 >>> pd.api.types.pandas_dtype(int)
1847 dtype('int64')
1848 """
1849 # short-circuit
1850 if isinstance(dtype, np.ndarray):
1851 return dtype.dtype
1852 elif isinstance(dtype, (np.dtype, ExtensionDtype)):
1853 return dtype
1854
1855 # builtin aliases
1856 if dtype is str and using_string_dtype():
1857 from pandas.core.arrays.string_ import StringDtype
1858
1859 return StringDtype(na_value=np.nan)
1860
1861 # registered extension types
1862 result = registry.find(dtype)
1863 if result is not None:
1864 if isinstance(result, type):
1865 # GH 31356, GH 54592
1866 warnings.warn(
1867 f"Instantiating {result.__name__} without any arguments."
1868 f"Pass a {result.__name__} instance to silence this warning.",
1869 UserWarning,
1870 stacklevel=find_stack_level(),
1871 )
1872 result = result()
1873 return result
1874
1875 # try a numpy dtype
1876 # raise a consistent TypeError if failed
1877 try:
1878 with warnings.catch_warnings():
1879 # TODO: warnings.catch_warnings can be removed when numpy>2.3.0
1880 # is the minimum version
1881 # GH#51523 - Series.astype(np.integer) doesn't show
1882 # numpy deprecation warning of np.integer
1883 # Hence enabling DeprecationWarning
1884 warnings.simplefilter("always", DeprecationWarning)
1885 npdtype = np.dtype(dtype)
1886 except TypeError:
1887 raise
1888 except ValueError as err:
1889 raise TypeError(f"data type '{dtype}' not understood") from err
1890
1891 # Any invalid dtype (such as pd.Timestamp) should raise an error.
1892 # np.dtype(invalid_type).kind = 0 for such objects. However, this will
1893 # also catch some valid dtypes such as object, np.object_ and 'object'
1894 # which we safeguard against by catching them earlier and returning
1895 # np.dtype(valid_dtype) before this condition is evaluated.
1896 if is_hashable(dtype) and dtype in [
1897 object,
1898 np.object_,
1899 "object",
1900 "O",
1901 "object_",
1902 ]:
1903 # check hashability to avoid errors/DeprecationWarning when we get
1904 # here and `dtype` is an array
1905 return npdtype
1906 elif npdtype.kind == "O":
1907 raise TypeError(f"dtype '{dtype}' not understood")
1908
1909 return npdtype
1910
1911
1912def is_all_strings(value: ArrayLike) -> bool:
1913 """
1914 Check if this is an array of strings that we should try parsing.
1915
1916 Includes object-dtype ndarray containing all-strings, StringArray,
1917 and Categorical with all-string categories.
1918 Does not include numpy string dtypes.
1919 """
1920 dtype = value.dtype
1921
1922 if isinstance(dtype, np.dtype):
1923 if len(value) == 0:
1924 return dtype == np.dtype("object")
1925 else:
1926 return dtype == np.dtype("object") and lib.is_string_array(
1927 np.asarray(value), skipna=False
1928 )
1929 elif isinstance(dtype, CategoricalDtype):
1930 return dtype.categories.inferred_type == "string"
1931 return dtype == "string"
1932
1933
1934__all__ = [
1935 "DT64NS_DTYPE",
1936 "INT64_DTYPE",
1937 "TD64NS_DTYPE",
1938 "classes",
1939 "ensure_float64",
1940 "ensure_python_int",
1941 "ensure_str",
1942 "infer_dtype_from_object",
1943 "is_1d_only_ea_dtype",
1944 "is_all_strings",
1945 "is_any_real_numeric_dtype",
1946 "is_array_like",
1947 "is_bool",
1948 "is_bool_dtype",
1949 "is_categorical_dtype",
1950 "is_complex",
1951 "is_complex_dtype",
1952 "is_dataclass",
1953 "is_datetime64_any_dtype",
1954 "is_datetime64_dtype",
1955 "is_datetime64_ns_dtype",
1956 "is_datetime64tz_dtype",
1957 "is_decimal",
1958 "is_dict_like",
1959 "is_dtype_equal",
1960 "is_ea_or_datetimelike_dtype",
1961 "is_extension_array_dtype",
1962 "is_file_like",
1963 "is_float_dtype",
1964 "is_int64_dtype",
1965 "is_integer_dtype",
1966 "is_interval_dtype",
1967 "is_iterator",
1968 "is_named_tuple",
1969 "is_nested_list_like",
1970 "is_number",
1971 "is_numeric_dtype",
1972 "is_object_dtype",
1973 "is_period_dtype",
1974 "is_re",
1975 "is_re_compilable",
1976 "is_scipy_sparse",
1977 "is_sequence",
1978 "is_signed_integer_dtype",
1979 "is_sparse",
1980 "is_string_dtype",
1981 "is_string_or_object_np_dtype",
1982 "is_timedelta64_dtype",
1983 "is_timedelta64_ns_dtype",
1984 "is_unsigned_integer_dtype",
1985 "needs_i8_conversion",
1986 "pandas_dtype",
1987 "validate_all_hashable",
1988]