1from __future__ import annotations
2
3import operator
4from typing import (
5 TYPE_CHECKING,
6 Literal,
7 NoReturn,
8 cast,
9)
10import warnings
11
12import numpy as np
13
14from pandas._libs import lib
15from pandas._libs.missing import is_matching_na
16from pandas._libs.sparse import SparseIndex
17import pandas._libs.testing as _testing
18from pandas._libs.tslibs.np_datetime import compare_mismatched_resolutions
19from pandas.errors import Pandas4Warning
20from pandas.util._decorators import (
21 deprecate_kwarg,
22 set_module,
23)
24
25from pandas.core.dtypes.common import (
26 is_bool,
27 is_float_dtype,
28 is_integer_dtype,
29 is_number,
30 is_numeric_dtype,
31 needs_i8_conversion,
32)
33from pandas.core.dtypes.dtypes import (
34 CategoricalDtype,
35 DatetimeTZDtype,
36 ExtensionDtype,
37 NumpyEADtype,
38)
39from pandas.core.dtypes.missing import array_equivalent
40
41import pandas as pd
42from pandas import (
43 Categorical,
44 DataFrame,
45 DatetimeIndex,
46 Index,
47 IntervalDtype,
48 IntervalIndex,
49 MultiIndex,
50 PeriodIndex,
51 RangeIndex,
52 Series,
53 TimedeltaIndex,
54)
55from pandas.core.arrays import (
56 DatetimeArray,
57 ExtensionArray,
58 IntervalArray,
59 PeriodArray,
60 TimedeltaArray,
61)
62from pandas.core.arrays.datetimelike import DatetimeLikeArrayMixin
63from pandas.core.arrays.string_ import StringDtype
64from pandas.core.indexes.api import safe_sort_index
65
66from pandas.io.formats.printing import pprint_thing
67
68if TYPE_CHECKING:
69 from pandas._typing import DtypeObj
70
71
72def assert_almost_equal(
73 left,
74 right,
75 check_dtype: bool | Literal["equiv"] = "equiv",
76 rtol: float = 1.0e-5,
77 atol: float = 1.0e-8,
78 **kwargs,
79) -> None:
80 """
81 Check that the left and right objects are approximately equal.
82
83 By approximately equal, we refer to objects that are numbers or that
84 contain numbers which may be equivalent to specific levels of precision.
85
86 Parameters
87 ----------
88 left : object
89 right : object
90 check_dtype : bool or {'equiv'}, default 'equiv'
91 Check dtype if both a and b are the same type. If 'equiv' is passed in,
92 then `RangeIndex` and `Index` with int64 dtype are also considered
93 equivalent when doing type checking.
94 rtol : float, default 1e-5
95 Relative tolerance.
96 atol : float, default 1e-8
97 Absolute tolerance.
98 """
99 if isinstance(left, Index):
100 assert_index_equal(
101 left,
102 right,
103 check_exact=False,
104 exact=check_dtype,
105 rtol=rtol,
106 atol=atol,
107 **kwargs,
108 )
109
110 elif isinstance(left, Series):
111 assert_series_equal(
112 left,
113 right,
114 check_exact=False,
115 check_dtype=check_dtype,
116 rtol=rtol,
117 atol=atol,
118 **kwargs,
119 )
120
121 elif isinstance(left, DataFrame):
122 assert_frame_equal(
123 left,
124 right,
125 check_exact=False,
126 check_dtype=check_dtype,
127 rtol=rtol,
128 atol=atol,
129 **kwargs,
130 )
131
132 else:
133 # Other sequences.
134 if check_dtype:
135 if is_number(left) and is_number(right):
136 # Do not compare numeric classes, like np.float64 and float.
137 pass
138 elif is_bool(left) and is_bool(right):
139 # Do not compare bool classes, like np.bool_ and bool.
140 pass
141 else:
142 if isinstance(left, np.ndarray) or isinstance(right, np.ndarray):
143 obj = "numpy array"
144 else:
145 obj = "Input"
146 assert_class_equal(left, right, obj=obj)
147
148 # if we have "equiv", this becomes True
149 _testing.assert_almost_equal(
150 left, right, check_dtype=bool(check_dtype), rtol=rtol, atol=atol, **kwargs
151 )
152
153
154def _check_isinstance(left, right, cls) -> None:
155 """
156 Helper method for our assert_* methods that ensures that
157 the two objects being compared have the right type before
158 proceeding with the comparison.
159
160 Parameters
161 ----------
162 left : The first object being compared.
163 right : The second object being compared.
164 cls : The class type to check against.
165
166 Raises
167 ------
168 AssertionError : Either `left` or `right` is not an instance of `cls`.
169 """
170 cls_name = cls.__name__
171
172 if not isinstance(left, cls):
173 raise AssertionError(
174 f"{cls_name} Expected type {cls}, found {type(left)} instead"
175 )
176 if not isinstance(right, cls):
177 raise AssertionError(
178 f"{cls_name} Expected type {cls}, found {type(right)} instead"
179 )
180
181
182def assert_dict_equal(left, right, compare_keys: bool = True) -> None:
183 _check_isinstance(left, right, dict)
184 _testing.assert_dict_equal(left, right, compare_keys=compare_keys)
185
186
187@set_module("pandas.testing")
188def assert_index_equal(
189 left: Index,
190 right: Index,
191 exact: bool | str = "equiv",
192 check_names: bool = True,
193 check_exact: bool = True,
194 check_categorical: bool = True,
195 check_order: bool = True,
196 rtol: float = 1.0e-5,
197 atol: float = 1.0e-8,
198 obj: str | None = None,
199) -> None:
200 """
201 Check that left and right Index are equal.
202
203 Parameters
204 ----------
205 left : Index
206 The first index to compare.
207 right : Index
208 The second index to compare.
209 exact : bool or {'equiv'}, default 'equiv'
210 Whether to check the Index class, dtype and inferred_type
211 are identical. If 'equiv', then RangeIndex can be substituted for
212 Index with an int64 dtype as well.
213 check_names : bool, default True
214 Whether to check the names attribute.
215 check_exact : bool, default True
216 Whether to compare number exactly.
217 check_categorical : bool, default True
218 Whether to compare internal Categorical exactly.
219 check_order : bool, default True
220 Whether to compare the order of index entries as well as their values.
221 If True, both indexes must contain the same elements, in the same order.
222 If False, both indexes must contain the same elements, but in any order.
223 rtol : float, default 1e-5
224 Relative tolerance. Only used when check_exact is False.
225 atol : float, default 1e-8
226 Absolute tolerance. Only used when check_exact is False.
227 obj : str, default 'Index' or 'MultiIndex'
228 Specify object name being compared, internally used to show appropriate
229 assertion message.
230
231 See Also
232 --------
233 testing.assert_series_equal : Check that two Series are equal.
234 testing.assert_frame_equal : Check that two DataFrames are equal.
235
236 Examples
237 --------
238 >>> from pandas import testing as tm
239 >>> a = pd.Index([1, 2, 3])
240 >>> b = pd.Index([1, 2, 3])
241 >>> tm.assert_index_equal(a, b)
242 """
243 __tracebackhide__ = True
244
245 if obj is None:
246 obj = "MultiIndex" if isinstance(left, MultiIndex) else "Index"
247
248 def _check_types(left, right, obj: str = "Index") -> None:
249 if not exact:
250 return
251
252 assert_class_equal(left, right, exact=exact, obj=obj)
253 assert_attr_equal("inferred_type", left, right, obj=obj)
254
255 # Skip exact dtype checking when `check_categorical` is False
256 if isinstance(left.dtype, CategoricalDtype) and isinstance(
257 right.dtype, CategoricalDtype
258 ):
259 if check_categorical:
260 assert_attr_equal("dtype", left, right, obj=obj)
261 assert_index_equal(left.categories, right.categories, exact=exact)
262 return
263
264 assert_attr_equal("dtype", left, right, obj=obj)
265
266 # instance validation
267 _check_isinstance(left, right, Index)
268
269 # class / dtype comparison
270 _check_types(left, right, obj=obj)
271
272 # level comparison
273 if left.nlevels != right.nlevels:
274 msg1 = f"{obj} levels are different"
275 msg2 = f"{left.nlevels}, {left}"
276 msg3 = f"{right.nlevels}, {right}"
277 raise_assert_detail(obj, msg1, msg2, msg3)
278
279 # length comparison
280 if len(left) != len(right):
281 msg1 = f"{obj} length are different"
282 msg2 = f"{len(left)}, {left}"
283 msg3 = f"{len(right)}, {right}"
284 raise_assert_detail(obj, msg1, msg2, msg3)
285
286 # If order doesn't matter then sort the index entries
287 if not check_order:
288 left = safe_sort_index(left)
289 right = safe_sort_index(right)
290
291 # MultiIndex special comparison for little-friendly error messages
292 if isinstance(left, MultiIndex):
293 right = cast(MultiIndex, right)
294
295 for level in range(left.nlevels):
296 lobj = f"{obj} level [{level}]"
297 try:
298 # try comparison on levels/codes to avoid densifying MultiIndex
299 assert_index_equal(
300 left.levels[level],
301 right.levels[level],
302 exact=exact,
303 check_names=check_names,
304 check_exact=check_exact,
305 check_categorical=check_categorical,
306 rtol=rtol,
307 atol=atol,
308 obj=lobj,
309 )
310 assert_numpy_array_equal(left.codes[level], right.codes[level])
311 except AssertionError:
312 llevel = left.get_level_values(level)
313 rlevel = right.get_level_values(level)
314
315 assert_index_equal(
316 llevel,
317 rlevel,
318 exact=exact,
319 check_names=check_names,
320 check_exact=check_exact,
321 check_categorical=check_categorical,
322 rtol=rtol,
323 atol=atol,
324 obj=lobj,
325 )
326 # get_level_values may change dtype
327 _check_types(left.levels[level], right.levels[level], obj=lobj)
328
329 # skip exact index checking when `check_categorical` is False
330 elif check_exact and check_categorical:
331 if not left.equals(right):
332 # _values compare can raise TypeError (non-comparable
333 # categoricals (GH#61935)
334 try:
335 mismatch = left._values != right._values
336 except TypeError:
337 raise_assert_detail(
338 obj,
339 "types are not comparable (non-matching categorical categories)",
340 left,
341 right,
342 )
343
344 if not isinstance(mismatch, np.ndarray):
345 mismatch = cast("ExtensionArray", mismatch).fillna(True)
346
347 diff = np.sum(mismatch.astype(int)) * 100.0 / len(left)
348 msg = f"{obj} values are different ({np.round(diff, 5)} %)"
349 raise_assert_detail(obj, msg, left, right)
350 else:
351 # if we have "equiv", this becomes True
352 exact_bool = bool(exact)
353 _testing.assert_almost_equal(
354 left.values,
355 right.values,
356 rtol=rtol,
357 atol=atol,
358 check_dtype=exact_bool,
359 obj=obj,
360 lobj=left,
361 robj=right,
362 )
363
364 # metadata comparison
365 if check_names:
366 assert_attr_equal("names", left, right, obj=obj)
367 if isinstance(left, PeriodIndex) or isinstance(right, PeriodIndex):
368 assert_attr_equal("dtype", left, right, obj=obj)
369 if isinstance(left, IntervalIndex) or isinstance(right, IntervalIndex):
370 assert_interval_array_equal(left._values, right._values)
371
372 if check_categorical:
373 if isinstance(left.dtype, CategoricalDtype) or isinstance(
374 right.dtype, CategoricalDtype
375 ):
376 assert_categorical_equal(left._values, right._values, obj=f"{obj} category")
377
378
379def assert_class_equal(
380 left, right, exact: bool | str = True, obj: str = "Input"
381) -> None:
382 """
383 Checks classes are equal.
384 """
385 __tracebackhide__ = True
386
387 def repr_class(x):
388 if isinstance(x, Index):
389 # return Index as it is to include values in the error message
390 return x
391
392 return type(x).__name__
393
394 def is_class_equiv(idx: Index) -> bool:
395 """Classes that are a RangeIndex (sub-)instance or exactly an `Index` .
396
397 This only checks class equivalence. There is a separate check that the
398 dtype is int64.
399 """
400 return type(idx) is Index or isinstance(idx, RangeIndex)
401
402 if type(left) == type(right):
403 return
404
405 if exact == "equiv":
406 if is_class_equiv(left) and is_class_equiv(right):
407 return
408
409 msg = f"{obj} classes are different"
410 raise_assert_detail(obj, msg, repr_class(left), repr_class(right))
411
412
413def assert_attr_equal(attr: str, left, right, obj: str = "Attributes") -> None:
414 """
415 Check attributes are equal. Both objects must have attribute.
416
417 Parameters
418 ----------
419 attr : str
420 Attribute name being compared.
421 left : object
422 right : object
423 obj : str, default 'Attributes'
424 Specify object name being compared, internally used to show appropriate
425 assertion message
426 """
427 __tracebackhide__ = True
428
429 left_attr = getattr(left, attr)
430 right_attr = getattr(right, attr)
431
432 if left_attr is right_attr or is_matching_na(left_attr, right_attr):
433 # e.g. both np.nan, both NaT, both pd.NA, ...
434 return None
435
436 try:
437 result = left_attr == right_attr
438 except TypeError:
439 # datetimetz on rhs may raise TypeError
440 result = False
441 if (left_attr is pd.NA) ^ (right_attr is pd.NA):
442 result = False
443 elif not isinstance(result, bool):
444 result = result.all()
445
446 if not result:
447 msg = f'Attribute "{attr}" are different'
448 raise_assert_detail(obj, msg, left_attr, right_attr)
449 return None
450
451
452def assert_is_sorted(seq) -> None:
453 """Assert that the sequence is sorted."""
454 if isinstance(seq, (Index, Series)):
455 seq = seq.values
456 # sorting does not change precisions
457 if isinstance(seq, np.ndarray):
458 assert_numpy_array_equal(seq, np.sort(np.array(seq)))
459 else:
460 assert_extension_array_equal(seq, seq[seq.argsort()])
461
462
463def assert_categorical_equal(
464 left,
465 right,
466 check_dtype: bool = True,
467 check_category_order: bool = True,
468 obj: str = "Categorical",
469) -> None:
470 """
471 Test that Categoricals are equivalent.
472
473 Parameters
474 ----------
475 left : Categorical
476 right : Categorical
477 check_dtype : bool, default True
478 Check that integer dtype of the codes are the same.
479 check_category_order : bool, default True
480 Whether the order of the categories should be compared, which
481 implies identical integer codes. If False, only the resulting
482 values are compared. The ordered attribute is
483 checked regardless.
484 obj : str, default 'Categorical'
485 Specify object name being compared, internally used to show appropriate
486 assertion message.
487 """
488 _check_isinstance(left, right, Categorical)
489
490 exact: bool | str
491 if isinstance(left.categories, RangeIndex) or isinstance(
492 right.categories, RangeIndex
493 ):
494 exact = "equiv"
495 else:
496 # We still want to require exact matches for Index
497 exact = True
498
499 if check_category_order:
500 assert_index_equal(
501 left.categories, right.categories, obj=f"{obj}.categories", exact=exact
502 )
503 assert_numpy_array_equal(
504 left.codes, right.codes, check_dtype=check_dtype, obj=f"{obj}.codes"
505 )
506 else:
507 try:
508 lc = left.categories.sort_values()
509 rc = right.categories.sort_values()
510 except TypeError:
511 # e.g. '<' not supported between instances of 'int' and 'str'
512 lc, rc = left.categories, right.categories
513 assert_index_equal(lc, rc, obj=f"{obj}.categories", exact=exact)
514 assert_index_equal(
515 left.categories.take(left.codes),
516 right.categories.take(right.codes),
517 obj=f"{obj}.values",
518 exact=exact,
519 )
520
521 assert_attr_equal("ordered", left, right, obj=obj)
522
523
524def assert_interval_array_equal(
525 left, right, exact: bool | Literal["equiv"] = "equiv", obj: str = "IntervalArray"
526) -> None:
527 """
528 Test that two IntervalArrays are equivalent.
529
530 Parameters
531 ----------
532 left, right : IntervalArray
533 The IntervalArrays to compare.
534 exact : bool or {'equiv'}, default 'equiv'
535 Whether to check the Index class, dtype and inferred_type
536 are identical. If 'equiv', then RangeIndex can be substituted for
537 Index with an int64 dtype as well.
538 obj : str, default 'IntervalArray'
539 Specify object name being compared, internally used to show appropriate
540 assertion message
541 """
542 _check_isinstance(left, right, IntervalArray)
543
544 kwargs = {}
545 if left._left.dtype.kind in "mM":
546 # We have a DatetimeArray or TimedeltaArray
547 kwargs["check_freq"] = False
548
549 assert_equal(left._left, right._left, obj=f"{obj}.left", **kwargs)
550 assert_equal(left._right, right._right, obj=f"{obj}.right", **kwargs)
551
552 assert_attr_equal("closed", left, right, obj=obj)
553
554
555def assert_period_array_equal(left, right, obj: str = "PeriodArray") -> None:
556 _check_isinstance(left, right, PeriodArray)
557
558 assert_numpy_array_equal(left._ndarray, right._ndarray, obj=f"{obj}._ndarray")
559 assert_attr_equal("dtype", left, right, obj=obj)
560
561
562def assert_datetime_array_equal(
563 left, right, obj: str = "DatetimeArray", check_freq: bool = True
564) -> None:
565 __tracebackhide__ = True
566 _check_isinstance(left, right, DatetimeArray)
567
568 assert_numpy_array_equal(left._ndarray, right._ndarray, obj=f"{obj}._ndarray")
569 if check_freq:
570 assert_attr_equal("freq", left, right, obj=obj)
571 assert_attr_equal("tz", left, right, obj=obj)
572
573
574def assert_timedelta_array_equal(
575 left, right, obj: str = "TimedeltaArray", check_freq: bool = True
576) -> None:
577 __tracebackhide__ = True
578 _check_isinstance(left, right, TimedeltaArray)
579 assert_numpy_array_equal(left._ndarray, right._ndarray, obj=f"{obj}._ndarray")
580 if check_freq:
581 assert_attr_equal("freq", left, right, obj=obj)
582
583
584def raise_assert_detail(
585 obj, message, left, right, diff=None, first_diff=None, index_values=None
586) -> NoReturn:
587 __tracebackhide__ = True
588
589 msg = f"""{obj} are different
590
591{message}"""
592
593 if isinstance(index_values, Index):
594 index_values = np.asarray(index_values)
595
596 if isinstance(index_values, np.ndarray):
597 msg += f"\n[index]: {pprint_thing(index_values)}"
598
599 if isinstance(left, np.ndarray):
600 left = pprint_thing(left)
601 elif isinstance(left, (CategoricalDtype, StringDtype, NumpyEADtype)):
602 left = repr(left)
603
604 if isinstance(right, np.ndarray):
605 right = pprint_thing(right)
606 elif isinstance(right, (CategoricalDtype, StringDtype, NumpyEADtype)):
607 right = repr(right)
608
609 msg += f"""
610[left]: {left}
611[right]: {right}"""
612
613 if diff is not None:
614 msg += f"\n[diff]: {diff}"
615
616 if first_diff is not None:
617 msg += f"\n{first_diff}"
618
619 raise AssertionError(msg)
620
621
622def assert_numpy_array_equal(
623 left,
624 right,
625 strict_nan: bool = False,
626 check_dtype: bool | Literal["equiv"] = True,
627 err_msg=None,
628 check_same=None,
629 obj: str = "numpy array",
630 index_values=None,
631) -> None:
632 """
633 Check that 'np.ndarray' is equivalent.
634
635 Parameters
636 ----------
637 left, right : numpy.ndarray or iterable
638 The two arrays to be compared.
639 strict_nan : bool, default False
640 If True, consider NaN and None to be different.
641 check_dtype : bool, default True
642 Check dtype if both a and b are np.ndarray.
643 err_msg : str, default None
644 If provided, used as assertion message.
645 check_same : None|'copy'|'same', default None
646 Ensure left and right refer/do not refer to the same memory area.
647 obj : str, default 'numpy array'
648 Specify object name being compared, internally used to show appropriate
649 assertion message.
650 index_values : Index | numpy.ndarray, default None
651 optional index (shared by both left and right), used in output.
652 """
653 __tracebackhide__ = True
654
655 # instance validation
656 # Show a detailed error message when classes are different
657 assert_class_equal(left, right, obj=obj)
658 # both classes must be an np.ndarray
659 _check_isinstance(left, right, np.ndarray)
660
661 def _get_base(obj):
662 return obj.base if getattr(obj, "base", None) is not None else obj
663
664 left_base = _get_base(left)
665 right_base = _get_base(right)
666
667 if check_same == "same":
668 if left_base is not right_base:
669 raise AssertionError(f"{left_base!r} is not {right_base!r}")
670 elif check_same == "copy":
671 if left_base is right_base:
672 raise AssertionError(f"{left_base!r} is {right_base!r}")
673
674 def _raise(left, right, err_msg) -> NoReturn:
675 if err_msg is None:
676 if left.shape != right.shape:
677 raise_assert_detail(
678 obj, f"{obj} shapes are different", left.shape, right.shape
679 )
680
681 diff = 0
682 for left_arr, right_arr in zip(left, right, strict=True):
683 # count up differences
684 if not array_equivalent(left_arr, right_arr, strict_nan=strict_nan):
685 diff += 1
686
687 diff = diff * 100.0 / left.size
688 msg = f"{obj} values are different ({np.round(diff, 5)} %)"
689 raise_assert_detail(obj, msg, left, right, index_values=index_values)
690
691 raise AssertionError(err_msg)
692
693 # compare shape and values
694 if not array_equivalent(left, right, strict_nan=strict_nan):
695 _raise(left, right, err_msg)
696
697 if check_dtype:
698 if isinstance(left, np.ndarray) and isinstance(right, np.ndarray):
699 assert_attr_equal("dtype", left, right, obj=obj)
700
701
702@set_module("pandas.testing")
703def assert_extension_array_equal(
704 left,
705 right,
706 check_dtype: bool | Literal["equiv"] = True,
707 index_values=None,
708 check_exact: bool | lib.NoDefault = lib.no_default,
709 rtol: float | lib.NoDefault = lib.no_default,
710 atol: float | lib.NoDefault = lib.no_default,
711 obj: str = "ExtensionArray",
712) -> None:
713 """
714 Check that left and right ExtensionArrays are equal.
715
716 This method compares two ``ExtensionArray`` instances for equality,
717 including checks for missing values, the dtype of the arrays, and
718 the exactness of the comparison (or tolerance when comparing floats).
719
720 Parameters
721 ----------
722 left, right : ExtensionArray
723 The two arrays to compare.
724 check_dtype : bool, default True
725 Whether to check if the ExtensionArray dtypes are identical.
726 index_values : Index | numpy.ndarray, default None
727 Optional index (shared by both left and right), used in output.
728 check_exact : bool, default False
729 Whether to compare number exactly.
730
731 .. versionchanged:: 2.2.0
732
733 Defaults to True for integer dtypes if none of
734 ``check_exact``, ``rtol`` and ``atol`` are specified.
735 rtol : float, default 1e-5
736 Relative tolerance. Only used when check_exact is False.
737 atol : float, default 1e-8
738 Absolute tolerance. Only used when check_exact is False.
739 obj : str, default 'ExtensionArray'
740 Specify object name being compared, internally used to show appropriate
741 assertion message.
742
743 .. versionadded:: 2.0.0
744
745 See Also
746 --------
747 testing.assert_series_equal : Check that left and right ``Series`` are equal.
748 testing.assert_frame_equal : Check that left and right ``DataFrame`` are equal.
749 testing.assert_index_equal : Check that left and right ``Index`` are equal.
750
751 Notes
752 -----
753 Missing values are checked separately from valid values.
754 A mask of missing values is computed for each and checked to match.
755 The remaining all-valid values are cast to object dtype and checked.
756
757 Examples
758 --------
759 >>> from pandas import testing as tm
760 >>> a = pd.Series([1, 2, 3, 4])
761 >>> b, c = a.array, a.array
762 >>> tm.assert_extension_array_equal(b, c)
763 """
764 if (
765 check_exact is lib.no_default
766 and rtol is lib.no_default
767 and atol is lib.no_default
768 ):
769 check_exact = (
770 is_numeric_dtype(left.dtype) and not is_float_dtype(left.dtype)
771 ) or (is_numeric_dtype(right.dtype) and not is_float_dtype(right.dtype))
772 elif check_exact is lib.no_default:
773 check_exact = False
774
775 rtol = rtol if rtol is not lib.no_default else 1.0e-5
776 atol = atol if atol is not lib.no_default else 1.0e-8
777
778 assert isinstance(left, ExtensionArray), "left is not an ExtensionArray"
779 assert isinstance(right, ExtensionArray), "right is not an ExtensionArray"
780 if check_dtype:
781 assert_attr_equal("dtype", left, right, obj=f"Attributes of {obj}")
782
783 if (
784 isinstance(left, DatetimeLikeArrayMixin)
785 and isinstance(right, DatetimeLikeArrayMixin)
786 and type(right) == type(left)
787 ):
788 # GH 52449
789 if not check_dtype and left.dtype.kind in "mM":
790 if not isinstance(left.dtype, np.dtype):
791 l_unit = cast(DatetimeTZDtype, left.dtype).unit
792 else:
793 l_unit = np.datetime_data(left.dtype)[0]
794 if not isinstance(right.dtype, np.dtype):
795 r_unit = cast(DatetimeTZDtype, right.dtype).unit
796 else:
797 r_unit = np.datetime_data(right.dtype)[0]
798 if (
799 l_unit != r_unit
800 and compare_mismatched_resolutions(
801 left._ndarray, right._ndarray, operator.eq
802 ).all()
803 ):
804 return
805 # Avoid slow object-dtype comparisons
806 # np.asarray for case where we have an np.MaskedArray
807 assert_numpy_array_equal(
808 np.asarray(left.asi8),
809 np.asarray(right.asi8),
810 index_values=index_values,
811 obj=obj,
812 )
813 return
814
815 left_na = np.asarray(left.isna())
816 right_na = np.asarray(right.isna())
817 assert_numpy_array_equal(
818 left_na, right_na, obj=f"{obj} NA mask", index_values=index_values
819 )
820
821 # Specifically for StringArrayNumpySemantics, validate here we have a valid array
822 if (
823 isinstance(left.dtype, StringDtype)
824 and left.dtype.storage == "python"
825 and left.dtype.na_value is np.nan
826 ):
827 assert np.all(
828 [np.isnan(val) for val in left._ndarray[left_na]] # type: ignore[attr-defined]
829 ), "wrong missing value sentinels"
830 if (
831 isinstance(right.dtype, StringDtype)
832 and right.dtype.storage == "python"
833 and right.dtype.na_value is np.nan
834 ):
835 assert np.all(
836 [np.isnan(val) for val in right._ndarray[right_na]] # type: ignore[attr-defined]
837 ), "wrong missing value sentinels"
838
839 left_valid = left[~left_na].to_numpy(dtype=object)
840 right_valid = right[~right_na].to_numpy(dtype=object)
841 if check_exact:
842 assert_numpy_array_equal(
843 left_valid, right_valid, obj=obj, index_values=index_values
844 )
845 else:
846 _testing.assert_almost_equal(
847 left_valid,
848 right_valid,
849 check_dtype=bool(check_dtype),
850 rtol=rtol,
851 atol=atol,
852 obj=obj,
853 index_values=index_values,
854 )
855
856
857# This could be refactored to use the NDFrame.equals method
858@set_module("pandas.testing")
859@deprecate_kwarg(Pandas4Warning, "check_datetimelike_compat", new_arg_name=None)
860def assert_series_equal(
861 left,
862 right,
863 check_dtype: bool | Literal["equiv"] = True,
864 check_index_type: bool | Literal["equiv"] = "equiv",
865 check_series_type: bool = True,
866 check_names: bool = True,
867 check_exact: bool | lib.NoDefault = lib.no_default,
868 check_datetimelike_compat: bool = False,
869 check_categorical: bool = True,
870 check_category_order: bool = True,
871 check_freq: bool = True,
872 check_flags: bool = True,
873 rtol: float | lib.NoDefault = lib.no_default,
874 atol: float | lib.NoDefault = lib.no_default,
875 obj: str = "Series",
876 *,
877 check_index: bool = True,
878 check_like: bool = False,
879) -> None:
880 """
881 Check that left and right Series are equal.
882
883 Parameters
884 ----------
885 left : Series
886 First Series to compare.
887 right : Series
888 Second Series to compare.
889 check_dtype : bool, default True
890 Whether to check the Series dtype is identical.
891 check_index_type : bool or {'equiv'}, default 'equiv'
892 Whether to check the Index class, dtype and inferred_type
893 are identical.
894 check_series_type : bool, default True
895 Whether to check the Series class is identical.
896 check_names : bool, default True
897 Whether to check the Series and Index names attribute.
898 check_exact : bool, default False
899 Whether to compare number exactly. This also applies when checking
900 Index equivalence.
901
902 .. versionchanged:: 2.2.0
903
904 Defaults to True for integer dtypes if none of
905 ``check_exact``, ``rtol`` and ``atol`` are specified.
906
907 .. versionchanged:: 3.0.0
908
909 check_exact for comparing the Indexes defaults to True by
910 checking if an Index is of integer dtypes.
911
912 check_datetimelike_compat : bool, default False
913 Compare datetime-like which is comparable ignoring dtype.
914
915 .. deprecated:: 3.0
916
917 check_categorical : bool, default True
918 Whether to compare internal Categorical exactly.
919 check_category_order : bool, default True
920 Whether to compare category order of internal Categoricals.
921 check_freq : bool, default True
922 Whether to check the `freq` attribute on a DatetimeIndex or TimedeltaIndex.
923 check_flags : bool, default True
924 Whether to check the `flags` attribute.
925 rtol : float, default 1e-5
926 Relative tolerance. Only used when check_exact is False.
927 atol : float, default 1e-8
928 Absolute tolerance. Only used when check_exact is False.
929 obj : str, default 'Series'
930 Specify object name being compared, internally used to show appropriate
931 assertion message.
932 check_index : bool, default True
933 Whether to check index equivalence. If False, then compare only values.
934 check_like : bool, default False
935 If True, ignore the order of the index. Must be False if check_index is False.
936 Note: same labels must be with the same data.
937
938 See Also
939 --------
940 testing.assert_index_equal : Check that two Indexes are equal.
941 testing.assert_frame_equal : Check that two DataFrames are equal.
942
943 Examples
944 --------
945 >>> from pandas import testing as tm
946 >>> a = pd.Series([1, 2, 3, 4])
947 >>> b = pd.Series([1, 2, 3, 4])
948 >>> tm.assert_series_equal(a, b)
949 """
950 __tracebackhide__ = True
951 if (
952 check_exact is lib.no_default
953 and rtol is lib.no_default
954 and atol is lib.no_default
955 ):
956 check_exact = (
957 is_numeric_dtype(left.dtype) and not is_float_dtype(left.dtype)
958 ) or (is_numeric_dtype(right.dtype) and not is_float_dtype(right.dtype))
959 left_index_dtypes = (
960 [left.index.dtype] if left.index.nlevels == 1 else left.index.dtypes
961 )
962 right_index_dtypes = (
963 [right.index.dtype] if right.index.nlevels == 1 else right.index.dtypes
964 )
965 check_exact_index = all(
966 dtype.kind in "iu" for dtype in left_index_dtypes
967 ) or all(dtype.kind in "iu" for dtype in right_index_dtypes)
968 elif check_exact is lib.no_default:
969 check_exact = False
970 check_exact_index = False
971 else:
972 check_exact_index = check_exact
973
974 rtol = rtol if rtol is not lib.no_default else 1.0e-5
975 atol = atol if atol is not lib.no_default else 1.0e-8
976
977 if not check_index and check_like:
978 raise ValueError("check_like must be False if check_index is False")
979
980 # instance validation
981 _check_isinstance(left, right, Series)
982
983 if check_series_type:
984 assert_class_equal(left, right, obj=obj)
985
986 # length comparison
987 if len(left) != len(right):
988 msg1 = f"{len(left)}, {left.index}"
989 msg2 = f"{len(right)}, {right.index}"
990 raise_assert_detail(obj, "Series length are different", msg1, msg2)
991
992 if check_flags:
993 assert left.flags == right.flags, f"{left.flags!r} != {right.flags!r}"
994
995 if check_index:
996 # GH #38183
997 assert_index_equal(
998 left.index,
999 right.index,
1000 exact=check_index_type,
1001 check_names=check_names,
1002 check_exact=check_exact_index,
1003 check_categorical=check_categorical,
1004 check_order=not check_like,
1005 rtol=rtol,
1006 atol=atol,
1007 obj=f"{obj}.index",
1008 )
1009
1010 if check_like:
1011 left = left.reindex_like(right)
1012
1013 if check_freq and isinstance(left.index, (DatetimeIndex, TimedeltaIndex)):
1014 lidx = left.index
1015 ridx = right.index
1016 assert lidx.freq == ridx.freq, (lidx.freq, ridx.freq)
1017
1018 if check_dtype:
1019 # We want to skip exact dtype checking when `check_categorical`
1020 # is False. We'll still raise if only one is a `Categorical`,
1021 # regardless of `check_categorical`
1022 if (
1023 isinstance(left.dtype, CategoricalDtype)
1024 and isinstance(right.dtype, CategoricalDtype)
1025 and not check_categorical
1026 ):
1027 pass
1028 else:
1029 assert_attr_equal("dtype", left, right, obj=f"Attributes of {obj}")
1030 if check_exact:
1031 left_values = left._values
1032 right_values = right._values
1033 # Only check exact if dtype is numeric
1034 if isinstance(left_values, ExtensionArray) and isinstance(
1035 right_values, ExtensionArray
1036 ):
1037 assert_extension_array_equal(
1038 left_values,
1039 right_values,
1040 check_dtype=check_dtype,
1041 index_values=left.index,
1042 obj=str(obj),
1043 )
1044 else:
1045 # convert both to NumPy if not, check_dtype would raise earlier
1046 lv, rv = left_values, right_values
1047 if isinstance(left_values, ExtensionArray):
1048 lv = left_values.to_numpy()
1049 if isinstance(right_values, ExtensionArray):
1050 rv = right_values.to_numpy()
1051 assert_numpy_array_equal(
1052 lv,
1053 rv,
1054 check_dtype=check_dtype,
1055 obj=str(obj),
1056 index_values=left.index,
1057 )
1058 elif check_datetimelike_compat and (
1059 needs_i8_conversion(left.dtype) or needs_i8_conversion(right.dtype)
1060 ):
1061 # we want to check only if we have compat dtypes
1062 # e.g. integer and M|m are NOT compat, but we can simply check
1063 # the values in that case
1064
1065 # datetimelike may have different objects (e.g. datetime.datetime
1066 # vs Timestamp) but will compare equal
1067 if not Index(left._values).equals(Index(right._values)):
1068 msg = (
1069 f"[datetimelike_compat=True] {left._values} "
1070 f"is not equal to {right._values}."
1071 )
1072 raise AssertionError(msg)
1073 elif isinstance(left.dtype, IntervalDtype) and isinstance(
1074 right.dtype, IntervalDtype
1075 ):
1076 assert_interval_array_equal(left.array, right.array)
1077 elif isinstance(left.dtype, CategoricalDtype) or isinstance(
1078 right.dtype, CategoricalDtype
1079 ):
1080 _testing.assert_almost_equal(
1081 left._values,
1082 right._values,
1083 rtol=rtol,
1084 atol=atol,
1085 check_dtype=bool(check_dtype),
1086 obj=str(obj),
1087 index_values=left.index,
1088 )
1089 elif isinstance(left.dtype, ExtensionDtype) and isinstance(
1090 right.dtype, ExtensionDtype
1091 ):
1092 assert_extension_array_equal(
1093 left._values,
1094 right._values,
1095 rtol=rtol,
1096 atol=atol,
1097 check_dtype=check_dtype,
1098 index_values=left.index,
1099 obj=str(obj),
1100 )
1101 elif is_extension_array_dtype_and_needs_i8_conversion(
1102 left.dtype, right.dtype
1103 ) or is_extension_array_dtype_and_needs_i8_conversion(right.dtype, left.dtype):
1104 assert_extension_array_equal(
1105 left._values,
1106 right._values,
1107 check_dtype=check_dtype,
1108 index_values=left.index,
1109 obj=str(obj),
1110 )
1111 elif needs_i8_conversion(left.dtype) and needs_i8_conversion(right.dtype):
1112 # DatetimeArray or TimedeltaArray
1113 assert_extension_array_equal(
1114 left._values,
1115 right._values,
1116 check_dtype=check_dtype,
1117 index_values=left.index,
1118 obj=str(obj),
1119 )
1120 else:
1121 _testing.assert_almost_equal(
1122 left._values,
1123 right._values,
1124 rtol=rtol,
1125 atol=atol,
1126 check_dtype=bool(check_dtype),
1127 obj=str(obj),
1128 index_values=left.index,
1129 )
1130
1131 # metadata comparison
1132 if check_names:
1133 assert_attr_equal("name", left, right, obj=obj)
1134
1135 if check_categorical:
1136 if isinstance(left.dtype, CategoricalDtype) or isinstance(
1137 right.dtype, CategoricalDtype
1138 ):
1139 assert_categorical_equal(
1140 left._values,
1141 right._values,
1142 obj=f"{obj} category",
1143 check_category_order=check_category_order,
1144 )
1145
1146
1147# This could be refactored to use the NDFrame.equals method
1148@set_module("pandas.testing")
1149@deprecate_kwarg(Pandas4Warning, "check_datetimelike_compat", new_arg_name=None)
1150def assert_frame_equal(
1151 left,
1152 right,
1153 check_dtype: bool | Literal["equiv"] = True,
1154 check_index_type: bool | Literal["equiv"] = "equiv",
1155 check_column_type: bool | Literal["equiv"] = "equiv",
1156 check_frame_type: bool = True,
1157 check_names: bool = True,
1158 by_blocks: bool = False,
1159 check_exact: bool | lib.NoDefault = lib.no_default,
1160 check_datetimelike_compat: bool = False,
1161 check_categorical: bool = True,
1162 check_like: bool = False,
1163 check_freq: bool = True,
1164 check_flags: bool = True,
1165 rtol: float | lib.NoDefault = lib.no_default,
1166 atol: float | lib.NoDefault = lib.no_default,
1167 obj: str = "DataFrame",
1168) -> None:
1169 """
1170 Check that left and right DataFrame are equal.
1171
1172 This function is intended to compare two DataFrames and output any
1173 differences. It is mostly intended for use in unit tests.
1174 Additional parameters allow varying the strictness of the
1175 equality checks performed.
1176
1177 Parameters
1178 ----------
1179 left : DataFrame
1180 First DataFrame to compare.
1181 right : DataFrame
1182 Second DataFrame to compare.
1183 check_dtype : bool, default True
1184 Whether to check the DataFrame dtype is identical.
1185 check_index_type : bool or {'equiv'}, default 'equiv'
1186 Whether to check the Index class, dtype and inferred_type
1187 are identical.
1188 check_column_type : bool or {'equiv'}, default 'equiv'
1189 Whether to check the columns class, dtype and inferred_type
1190 are identical. Is passed as the ``exact`` argument of
1191 :func:`assert_index_equal`.
1192 check_frame_type : bool, default True
1193 Whether to check the DataFrame class is identical.
1194 check_names : bool, default True
1195 Whether to check that the `names` attribute for both the `index`
1196 and `column` attributes of the DataFrame is identical.
1197 by_blocks : bool, default False
1198 Specify how to compare internal data. If False, compare by columns.
1199 If True, compare by blocks.
1200 check_exact : bool, default False
1201 Whether to compare number exactly. If False, the comparison uses the
1202 relative tolerance (``rtol``) and absolute tolerance (``atol``)
1203 parameters to determine if two values are considered close,
1204 according to the formula: ``|a - b| <= (atol + rtol * |b|)``.
1205
1206 .. versionchanged:: 2.2.0
1207
1208 Defaults to True for integer dtypes if none of
1209 ``check_exact``, ``rtol`` and ``atol`` are specified.
1210 check_datetimelike_compat : bool, default False
1211 Compare datetime-like which is comparable ignoring dtype.
1212
1213 .. deprecated:: 3.0
1214
1215 check_categorical : bool, default True
1216 Whether to compare internal Categorical exactly.
1217 check_like : bool, default False
1218 If True, ignore the order of index & columns.
1219 Note: index labels must match their respective rows
1220 (same as in columns) - same labels must be with the same data.
1221 check_freq : bool, default True
1222 Whether to check the `freq` attribute on a DatetimeIndex or TimedeltaIndex.
1223 check_flags : bool, default True
1224 Whether to check the `flags` attribute.
1225 rtol : float, default 1e-5
1226 Relative tolerance. Only used when check_exact is False.
1227 atol : float, default 1e-8
1228 Absolute tolerance. Only used when check_exact is False.
1229 obj : str, default 'DataFrame'
1230 Specify object name being compared, internally used to show appropriate
1231 assertion message.
1232
1233 See Also
1234 --------
1235 assert_series_equal : Equivalent method for asserting Series equality.
1236 DataFrame.equals : Check DataFrame equality.
1237
1238 Examples
1239 --------
1240 This example shows comparing two DataFrames that are equal
1241 but with columns of differing dtypes.
1242
1243 >>> from pandas.testing import assert_frame_equal
1244 >>> df1 = pd.DataFrame({"a": [1, 2], "b": [3, 4]})
1245 >>> df2 = pd.DataFrame({"a": [1, 2], "b": [3.0, 4.0]})
1246
1247 df1 equals itself.
1248
1249 >>> assert_frame_equal(df1, df1)
1250
1251 df1 differs from df2 as column 'b' is of a different type.
1252
1253 >>> assert_frame_equal(df1, df2)
1254 Traceback (most recent call last):
1255 ...
1256 AssertionError: Attributes of DataFrame.iloc[:, 1] (column name="b") are different
1257
1258 Attribute "dtype" are different
1259 [left]: int64
1260 [right]: float64
1261
1262 Ignore differing dtypes in columns with check_dtype.
1263
1264 >>> assert_frame_equal(df1, df2, check_dtype=False)
1265 """
1266 __tracebackhide__ = True
1267 _rtol = rtol if rtol is not lib.no_default else 1.0e-5
1268 _atol = atol if atol is not lib.no_default else 1.0e-8
1269 _check_exact = check_exact if check_exact is not lib.no_default else False
1270
1271 # instance validation
1272 _check_isinstance(left, right, DataFrame)
1273
1274 if check_frame_type:
1275 assert isinstance(left, type(right))
1276 # assert_class_equal(left, right, obj=obj)
1277
1278 # shape comparison
1279 if left.shape != right.shape:
1280 raise_assert_detail(
1281 obj, f"{obj} shape mismatch", f"{left.shape!r}", f"{right.shape!r}"
1282 )
1283
1284 if check_flags:
1285 assert left.flags == right.flags, f"{left.flags!r} != {right.flags!r}"
1286
1287 # index comparison
1288 assert_index_equal(
1289 left.index,
1290 right.index,
1291 exact=check_index_type,
1292 check_names=check_names,
1293 check_exact=_check_exact,
1294 check_categorical=check_categorical,
1295 check_order=not check_like,
1296 rtol=_rtol,
1297 atol=_atol,
1298 obj=f"{obj}.index",
1299 )
1300
1301 # column comparison
1302 assert_index_equal(
1303 left.columns,
1304 right.columns,
1305 exact=check_column_type,
1306 check_names=check_names,
1307 check_exact=_check_exact,
1308 check_categorical=check_categorical,
1309 check_order=not check_like,
1310 rtol=_rtol,
1311 atol=_atol,
1312 obj=f"{obj}.columns",
1313 )
1314
1315 if check_like:
1316 left = left.reindex_like(right)
1317
1318 # compare by blocks
1319 if by_blocks:
1320 rblocks = right._to_dict_of_blocks()
1321 lblocks = left._to_dict_of_blocks()
1322 for dtype in list(set(list(lblocks.keys()) + list(rblocks.keys()))):
1323 assert dtype in lblocks
1324 assert dtype in rblocks
1325 assert_frame_equal(
1326 lblocks[dtype], rblocks[dtype], check_dtype=check_dtype, obj=obj
1327 )
1328
1329 # compare by columns
1330 else:
1331 for i, col in enumerate(left.columns):
1332 # We have already checked that columns match, so we can do
1333 # fast location-based lookups
1334 lcol = left._ixs(i, axis=1)
1335 rcol = right._ixs(i, axis=1)
1336
1337 # GH #38183
1338 # use check_index=False, because we do not want to run
1339 # assert_index_equal for each column,
1340 # as we already checked it for the whole dataframe before.
1341 with warnings.catch_warnings():
1342 warnings.filterwarnings(
1343 "ignore",
1344 message="the 'check_datetimelike_compat' keyword",
1345 category=Pandas4Warning,
1346 )
1347 assert_series_equal(
1348 lcol,
1349 rcol,
1350 check_dtype=check_dtype,
1351 check_index_type=check_index_type,
1352 check_exact=check_exact,
1353 check_names=check_names,
1354 check_datetimelike_compat=check_datetimelike_compat,
1355 check_categorical=check_categorical,
1356 check_freq=check_freq,
1357 obj=f'{obj}.iloc[:, {i}] (column name="{col}")',
1358 rtol=rtol,
1359 atol=atol,
1360 check_index=False,
1361 check_flags=False,
1362 )
1363
1364
1365def assert_equal(left, right, **kwargs) -> None:
1366 """
1367 Wrapper for tm.assert_*_equal to dispatch to the appropriate test function.
1368
1369 Parameters
1370 ----------
1371 left, right : Index, Series, DataFrame, ExtensionArray, or np.ndarray
1372 The two items to be compared.
1373 **kwargs
1374 All keyword arguments are passed through to the underlying assert method.
1375 """
1376 __tracebackhide__ = True
1377
1378 if isinstance(left, Index):
1379 assert_index_equal(left, right, **kwargs)
1380 if isinstance(left, (DatetimeIndex, TimedeltaIndex)):
1381 assert left.freq == right.freq, (left.freq, right.freq)
1382 elif isinstance(left, Series):
1383 assert_series_equal(left, right, **kwargs)
1384 elif isinstance(left, DataFrame):
1385 assert_frame_equal(left, right, **kwargs)
1386 elif isinstance(left, IntervalArray):
1387 assert_interval_array_equal(left, right, **kwargs)
1388 elif isinstance(left, PeriodArray):
1389 assert_period_array_equal(left, right, **kwargs)
1390 elif isinstance(left, DatetimeArray):
1391 assert_datetime_array_equal(left, right, **kwargs)
1392 elif isinstance(left, TimedeltaArray):
1393 assert_timedelta_array_equal(left, right, **kwargs)
1394 elif isinstance(left, ExtensionArray):
1395 assert_extension_array_equal(left, right, **kwargs)
1396 elif isinstance(left, np.ndarray):
1397 assert_numpy_array_equal(left, right, **kwargs)
1398 elif isinstance(left, str):
1399 assert kwargs == {}
1400 assert left == right
1401 else:
1402 assert kwargs == {}
1403 assert_almost_equal(left, right)
1404
1405
1406def assert_sp_array_equal(left, right) -> None:
1407 """
1408 Check that the left and right SparseArray are equal.
1409
1410 Parameters
1411 ----------
1412 left : SparseArray
1413 right : SparseArray
1414 """
1415 _check_isinstance(left, right, pd.arrays.SparseArray)
1416
1417 assert_numpy_array_equal(left.sp_values, right.sp_values)
1418
1419 # SparseIndex comparison
1420 assert isinstance(left.sp_index, SparseIndex)
1421 assert isinstance(right.sp_index, SparseIndex)
1422
1423 left_index = left.sp_index
1424 right_index = right.sp_index
1425
1426 if not left_index.equals(right_index):
1427 raise_assert_detail(
1428 "SparseArray.index", "index are not equal", left_index, right_index
1429 )
1430 else:
1431 # Just ensure a
1432 pass
1433
1434 assert_attr_equal("fill_value", left, right)
1435 assert_attr_equal("dtype", left, right)
1436 assert_numpy_array_equal(left.to_dense(), right.to_dense())
1437
1438
1439def assert_contains_all(iterable, dic) -> None:
1440 for k in iterable:
1441 assert k in dic, f"Did not contain item: {k!r}"
1442
1443
1444def assert_copy(iter1, iter2, **eql_kwargs) -> None:
1445 """
1446 iter1, iter2: iterables that produce elements
1447 comparable with assert_almost_equal
1448
1449 Checks that the elements are equal, but not
1450 the same object. (Does not check that items
1451 in sequences are also not the same object)
1452 """
1453 for elem1, elem2 in zip(iter1, iter2, strict=True):
1454 assert_almost_equal(elem1, elem2, **eql_kwargs)
1455 msg = (
1456 f"Expected object {type(elem1)!r} and object {type(elem2)!r} to be "
1457 "different objects, but they were the same object."
1458 )
1459 assert elem1 is not elem2, msg
1460
1461
1462def is_extension_array_dtype_and_needs_i8_conversion(
1463 left_dtype: DtypeObj, right_dtype: DtypeObj
1464) -> bool:
1465 """
1466 Checks that we have the combination of an ExtensionArraydtype and
1467 a dtype that should be converted to int64
1468
1469 Returns
1470 -------
1471 bool
1472
1473 Related to issue #37609
1474 """
1475 return isinstance(left_dtype, ExtensionDtype) and needs_i8_conversion(right_dtype)
1476
1477
1478def assert_indexing_slices_equivalent(ser: Series, l_slc: slice, i_slc: slice) -> None:
1479 """
1480 Check that ser.iloc[i_slc] matches ser.loc[l_slc] and, if applicable,
1481 ser[l_slc].
1482 """
1483 expected = ser.iloc[i_slc]
1484
1485 assert_series_equal(ser.loc[l_slc], expected)
1486
1487 if not is_integer_dtype(ser.index):
1488 # For integer indices, .loc and plain getitem are position-based.
1489 assert_series_equal(ser[l_slc], expected)
1490
1491
1492def assert_metadata_equivalent(
1493 left: DataFrame | Series, right: DataFrame | Series | None = None
1494) -> None:
1495 """
1496 Check that ._metadata attributes are equivalent.
1497 """
1498 for attr in left._metadata:
1499 val = getattr(left, attr, None)
1500 if right is None:
1501 assert val is None
1502 else:
1503 assert val == getattr(right, attr, None)