def test_is_matching_na_nan_matches_none(self): assert not libmissing.is_matching_na(None, np.nan) assert not libmissing.is_matching_na(np.nan, None) assert libmissing.is_matching_na(None, np.nan, nan_matches_none=True) assert libmissing.is_matching_na(np.nan, None, nan_matches_none=True)
def test_get_indexer_non_unique_nas(self, nulls_fixture): # even though this isn't non-unique, this should still work index = Index(["a", "b", nulls_fixture]) indexer, missing = index.get_indexer_non_unique([nulls_fixture]) expected_indexer = np.array([2], dtype=np.intp) expected_missing = np.array([], dtype=np.intp) tm.assert_numpy_array_equal(indexer, expected_indexer) tm.assert_numpy_array_equal(missing, expected_missing) # actually non-unique index = Index(["a", nulls_fixture, "b", nulls_fixture]) indexer, missing = index.get_indexer_non_unique([nulls_fixture]) expected_indexer = np.array([1, 3], dtype=np.intp) tm.assert_numpy_array_equal(indexer, expected_indexer) tm.assert_numpy_array_equal(missing, expected_missing) # matching-but-not-identical nans if is_matching_na(nulls_fixture, float("NaN")): index = Index(["a", float("NaN"), "b", float("NaN")]) match_but_not_identical = True elif is_matching_na(nulls_fixture, Decimal("NaN")): index = Index(["a", Decimal("NaN"), "b", Decimal("NaN")]) match_but_not_identical = True else: match_but_not_identical = False if match_but_not_identical: indexer, missing = index.get_indexer_non_unique([nulls_fixture]) expected_indexer = np.array([1, 3], dtype=np.intp) tm.assert_numpy_array_equal(indexer, expected_indexer) tm.assert_numpy_array_equal(missing, expected_missing)
def test_is_matching_na(self, nulls_fixture, nulls_fixture2): left = nulls_fixture right = nulls_fixture2 assert libmissing.is_matching_na(left, left) if left is right: assert libmissing.is_matching_na(left, right) elif is_float(left) and is_float(right): # np.nan vs float("NaN") we consider as matching assert libmissing.is_matching_na(left, right) else: assert not libmissing.is_matching_na(left, right)
def test_reductions_2d_axis_none(self, data, method, request): if not hasattr(data, method): pytest.skip("test is not applicable for this type/dtype") arr2d = data.reshape(1, -1) err_expected = None err_result = None try: expected = getattr(data, method)() except Exception as err: # if the 1D reduction is invalid, the 2D reduction should be as well err_expected = err try: result = getattr(arr2d, method)(axis=None) except Exception as err2: err_result = err2 else: result = getattr(arr2d, method)(axis=None) if err_result is not None or err_expected is not None: assert type(err_result) == type(err_expected) return assert is_matching_na(result, expected) or result == expected
def _maybe_match_name(a, b): """ Try to find a name to attach to the result of an operation between a and b. If only one of these has a `name` attribute, return that name. Otherwise return a consensus name if they match or None if they have different names. Parameters ---------- a : object b : object Returns ------- name : str or None See Also -------- pandas.core.common.consensus_name_attr """ a_has = hasattr(a, "name") b_has = hasattr(b, "name") if a_has and b_has: try: if a.name == b.name: return a.name elif is_matching_na(a.name, b.name): # e.g. both are np.nan return a.name else: return None except TypeError: # pd.NA if is_matching_na(a.name, b.name): return a.name return None except ValueError: # e.g. np.int64(1) vs (np.int64(1), np.int64(2)) return None elif a_has: return a.name elif b_has: return b.name return None
def test_equals_mismatched_nas(nulls_fixture, nulls_fixture2): # GH#39650 left = nulls_fixture right = nulls_fixture2 if hasattr(right, "copy"): right = right.copy() else: right = copy.copy(right) ser = Series([left], dtype=object) ser2 = Series([right], dtype=object) if is_matching_na(left, right): assert ser.equals(ser2) elif (left is None and is_float(right)) or (right is None and is_float(left)): assert ser.equals(ser2) else: assert not ser.equals(ser2)
def test_get_indexer_non_unique_np_nats(self, np_nat_fixture, np_nat_fixture2): expected_missing = np.array([], dtype=np.intp) # matching-but-not-identical nats if is_matching_na(np_nat_fixture, np_nat_fixture2): # ensure nats are different objects index = Index( np.array( [ "2021-10-02", np_nat_fixture.copy(), np_nat_fixture2.copy() ], dtype=object, ), dtype=object, ) # pass as index to prevent target from being casted to DatetimeIndex indexer, missing = index.get_indexer_non_unique( Index([np_nat_fixture], dtype=object)) expected_indexer = np.array([1, 2], dtype=np.intp) tm.assert_numpy_array_equal(indexer, expected_indexer) tm.assert_numpy_array_equal(missing, expected_missing) # dt64nat vs td64nat else: index = Index( np.array( [ "2021-10-02", np_nat_fixture, np_nat_fixture2, np_nat_fixture, np_nat_fixture2, ], dtype=object, ), dtype=object, ) # pass as index to prevent target from being casted to DatetimeIndex indexer, missing = index.get_indexer_non_unique( Index([np_nat_fixture], dtype=object)) expected_indexer = np.array([1, 3], dtype=np.intp) tm.assert_numpy_array_equal(indexer, expected_indexer) tm.assert_numpy_array_equal(missing, expected_missing)
def test_reductions_2d_axis1(self, data, method): arr2d = data.reshape(1, -1) try: result = getattr(arr2d, method)(axis=1) except Exception as err: try: getattr(data, method)() except Exception as err2: assert type(err) == type(err2) return else: raise AssertionError("Both reductions should raise or neither") # not necessarily type/dtype-preserving, so weaker assertions assert result.shape == (1, ) expected_scalar = getattr(data, method)() res = result[0] assert is_matching_na(res, expected_scalar) or res == expected_scalar
def assert_attr_equal(attr: str, left, right, obj: str = "Attributes"): """ Check attributes are equal. Both objects must have attribute. Parameters ---------- attr : str Attribute name being compared. left : object right : object obj : str, default 'Attributes' Specify object name being compared, internally used to show appropriate assertion message """ __tracebackhide__ = True left_attr = getattr(left, attr) right_attr = getattr(right, attr) if left_attr is right_attr: return True elif is_matching_na(left_attr, right_attr): # e.g. both np.nan, both NaT, both pd.NA, ... return True try: result = left_attr == right_attr except TypeError: # datetimetz on rhs may raise TypeError result = False if (left_attr is pd.NA) ^ (right_attr is pd.NA): result = False elif not isinstance(result, bool): result = result.all() if result: return True else: msg = f'Attribute "{attr}" are different' raise_assert_detail(obj, msg, left_attr, right_attr)