Alle Dateien aus dem Pythonkurs
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

222 lines
6.3 KiB

import cmath
import math
import warnings
import numpy as np
from numpy cimport import_array
import_array()
from pandas._libs.missing cimport (
checknull,
is_matching_na,
)
from pandas._libs.util cimport (
is_array,
is_complex_object,
is_real_number_object,
)
from pandas.util._exceptions import find_stack_level
from pandas.core.dtypes.missing import array_equivalent
cdef bint isiterable(obj):
return hasattr(obj, "__iter__")
cdef bint has_length(obj):
return hasattr(obj, "__len__")
cdef bint is_dictlike(obj):
return hasattr(obj, "keys") and hasattr(obj, "__getitem__")
cpdef assert_dict_equal(a, b, bint compare_keys=True):
assert is_dictlike(a) and is_dictlike(b), (
"Cannot compare dict objects, one or both is not dict-like"
)
a_keys = frozenset(a.keys())
b_keys = frozenset(b.keys())
if compare_keys:
assert a_keys == b_keys
for k in a_keys:
assert_almost_equal(a[k], b[k])
return True
cpdef assert_almost_equal(a, b,
rtol=1.e-5, atol=1.e-8,
bint check_dtype=True,
obj=None, lobj=None, robj=None, index_values=None):
"""
Check that left and right objects are almost equal.
Parameters
----------
a : object
b : object
rtol : float, default 1e-5
Relative tolerance.
atol : float, default 1e-8
Absolute tolerance.
check_dtype: bool, default True
check dtype if both a and b are np.ndarray.
obj : str, default None
Specify object name being compared, internally used to show
appropriate assertion message.
lobj : str, default None
Specify left object name being compared, internally used to show
appropriate assertion message.
robj : str, default None
Specify right object name being compared, internally used to show
appropriate assertion message.
index_values : ndarray, default None
Specify shared index values of objects being compared, internally used
to show appropriate assertion message.
"""
cdef:
double diff = 0.0
Py_ssize_t i, na, nb
double fa, fb
bint is_unequal = False, a_is_ndarray, b_is_ndarray
str first_diff = ""
if lobj is None:
lobj = a
if robj is None:
robj = b
if isinstance(a, set) or isinstance(b, set):
assert a == b, f"{a} != {b}"
return True
if isinstance(a, dict) or isinstance(b, dict):
return assert_dict_equal(a, b)
if isinstance(a, str) or isinstance(b, str):
assert a == b, f"{a} != {b}"
return True
a_is_ndarray = is_array(a)
b_is_ndarray = is_array(b)
if obj is None:
if a_is_ndarray or b_is_ndarray:
obj = "numpy array"
else:
obj = "Iterable"
if isiterable(a):
if not isiterable(b):
from pandas._testing import assert_class_equal
# classes can't be the same, to raise error
assert_class_equal(a, b, obj=obj)
assert has_length(a) and has_length(b), (
f"Can't compare objects without length, one or both is invalid: ({a}, {b})"
)
if a_is_ndarray and b_is_ndarray:
na, nb = a.size, b.size
if a.shape != b.shape:
from pandas._testing import raise_assert_detail
raise_assert_detail(
obj, f"{obj} shapes are different", a.shape, b.shape)
if check_dtype and a.dtype != b.dtype:
from pandas._testing import assert_attr_equal
assert_attr_equal("dtype", a, b, obj=obj)
if array_equivalent(a, b, strict_nan=True):
return True
else:
na, nb = len(a), len(b)
if na != nb:
from pandas._testing import raise_assert_detail
# if we have a small diff set, print it
if abs(na - nb) < 10:
r = list(set(a) ^ set(b))
else:
r = None
raise_assert_detail(obj, f"{obj} length are different", na, nb, r)
for i in range(len(a)):
try:
assert_almost_equal(a[i], b[i], rtol=rtol, atol=atol)
except AssertionError:
is_unequal = True
diff += 1
if not first_diff:
first_diff = (
f"At positional index {i}, first diff: {a[i]} != {b[i]}"
)
if is_unequal:
from pandas._testing import raise_assert_detail
msg = (f"{obj} values are different "
f"({np.round(diff * 100.0 / na, 5)} %)")
raise_assert_detail(
obj, msg, lobj, robj, first_diff=first_diff, index_values=index_values
)
return True
elif isiterable(b):
from pandas._testing import assert_class_equal
# classes can't be the same, to raise error
assert_class_equal(a, b, obj=obj)
if checknull(a):
# nan / None comparison
if is_matching_na(a, b, nan_matches_none=False):
return True
elif checknull(b):
# GH#18463
warnings.warn(
f"Mismatched null-like values {a} and {b} found. In a future "
"version, pandas equality-testing functions "
"(e.g. assert_frame_equal) will consider these not-matching "
"and raise.",
FutureWarning,
stacklevel=find_stack_level(),
)
return True
raise AssertionError(f"{a} != {b}")
elif checknull(b):
raise AssertionError(f"{a} != {b}")
if a == b:
# object comparison
return True
if is_real_number_object(a) and is_real_number_object(b):
fa, fb = a, b
if not math.isclose(fa, fb, rel_tol=rtol, abs_tol=atol):
assert False, (f"expected {fb:.5f} but got {fa:.5f}, "
f"with rtol={rtol}, atol={atol}")
return True
if is_complex_object(a) and is_complex_object(b):
if not cmath.isclose(a, b, rel_tol=rtol, abs_tol=atol):
assert False, (f"expected {b:.5f} but got {a:.5f}, "
f"with rtol={rtol}, atol={atol}")
return True
raise AssertionError(f"{a} != {b}")