pint-pandas
pint-pandas copied to clipboard
`numpy.allclose` not working for `PintArray`
Issue
import pandas as pd
import numpy as np
from pint_pandas import PintArray
>>> pa1 = pa2 = PintArray([1, 45, -4.5], 'm')
>>> np.allclose(pa1, pa2)
# ---------------------------------------------------------------------------
# TypeError Traceback (most recent call last)
# 16 pa = PintArray([1, 45, -4.5], 'm')
# ----> 17 np.allclose(pa1, pa2)
# <__array_function__ internals> in allclose(*args, **kwargs)
# ~\Anaconda3\envs\lb38\lib\site-packages\numpy\core\numeric.py in allclose(a, b, rtol, atol, equal_nan)
# 2248 """
# -> 2249 res = all(isclose(a, b, rtol=rtol, atol=atol, equal_nan=equal_nan))
# 2250 return bool(res)
# <__array_function__ internals> in isclose(*args, **kwargs)
# ~\Anaconda3\envs\lb38\lib\site-packages\numpy\core\numeric.py in isclose(a, b, rtol, atol, equal_nan)
# 2354
# -> 2355 xfin = isfinite(x)
# 2356 yfin = isfinite(y)
# TypeError: ufunc 'isfinite' not supported for the input types, and the inputs could not be safely coerced to any supported types according to the casting rule ''safe''
I'm on pint
version 0.18 and pint_pandas
0.2
Non-complete workaround
>>> pa1.quantity.units == pa2.quantity.units and np.allclose(pa1.quantity.m, pa2.quantity.m)
True
This is not watertight! Workaround incorrectly returns False
when comparing 1 m with 100 cm.
Watertight (?) workaround
def pintarray_allclose(pa1, pa2):
if pa1.quantity.dimensionality != pa2.quantity.dimensionality:
return False
a1 = pa1.quantity.magnitude
a2 = pa2.astype(f"pint[{pa1.quantity.units}]").quantity.magnitude
return np.allclose(a1, a2)
>>> pintarray_allclose(pa1, pa2)
True
>>> pintarray_allclose(pa1, pa2.astype('pint[km]'))
True
this will need __array_function__
implemented
as a workaround you can use pint's quantity:
np.allclose(pa1.quantity, pa2.quantity)
True