Numpy support#
Numpy functions that work on pint Quantity ndarray objects also work on PintArray.
In [1]: pa = PintArray([1, 2, np.nan, 4, 10], dtype="pint[m]")
In [2]: np.clip(pa, 3 * ureg.m, 5 * ureg.m)
Out[2]:
<PintArray>
[3.0, 3.0, <NA>, 4.0, 5.0]
Length: 5, dtype: pint[meter][Float64]
Note that this function errors when applied to a Series.
In [3]: df = pd.DataFrame({"A": pa})
In [4]: np.clip(df['A'], 3 * ureg.m, 5 * ureg.m)
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
Cell In[4], line 1
----> 1 np.clip(df['A'], 3 * ureg.m, 5 * ureg.m)
File ~/checkouts/readthedocs.org/user_builds/pint-pandas/envs/latest/lib/python3.11/site-packages/pint/facets/numpy/quantity.py:75, in NumpyQuantity.__array_function__(self, func, types, args, kwargs)
74 def __array_function__(self, func, types, args, kwargs):
---> 75 return numpy_wrap("function", func, args, kwargs, types)
File ~/checkouts/readthedocs.org/user_builds/pint-pandas/envs/latest/lib/python3.11/site-packages/pint/facets/numpy/numpy_func.py:1133, in numpy_wrap(func_type, func, args, kwargs, types)
1131 if name not in handled or any(is_upcast_type(t) for t in types):
1132 return NotImplemented
-> 1133 return handled[name](*args, **kwargs)
File ~/checkouts/readthedocs.org/user_builds/pint-pandas/envs/latest/lib/python3.11/site-packages/pint/facets/numpy/numpy_func.py:895, in implement_consistent_units_by_argument.<locals>.implementation(*args, **kwargs)
893 for i, unwrapped_unit_arg in enumerate(unwrapped_unit_args):
894 bound_args.arguments[valid_unit_arguments[i]] = unwrapped_unit_arg
--> 895 ret = func(*bound_args.args, **bound_args.kwargs)
897 # Conditionally wrap output
898 if wrap_output:
File ~/checkouts/readthedocs.org/user_builds/pint-pandas/envs/latest/lib/python3.11/site-packages/numpy/_core/fromnumeric.py:2296, in clip(a, a_min, a_max, out, min, max, **kwargs)
2292 elif min is not np._NoValue or max is not np._NoValue:
2293 raise ValueError("Passing `min` or `max` keyword argument when "
2294 "`a_min` and `a_max` are provided is forbidden.")
-> 2296 return _wrapfunc(a, 'clip', a_min, a_max, out=out, **kwargs)
File ~/checkouts/readthedocs.org/user_builds/pint-pandas/envs/latest/lib/python3.11/site-packages/numpy/_core/fromnumeric.py:51, in _wrapfunc(obj, method, *args, **kwds)
49 bound = getattr(obj, method, None)
50 if bound is None:
---> 51 return _wrapit(obj, method, *args, **kwds)
53 try:
54 return bound(*args, **kwds)
File ~/checkouts/readthedocs.org/user_builds/pint-pandas/envs/latest/lib/python3.11/site-packages/numpy/_core/fromnumeric.py:43, in _wrapit(obj, method, *args, **kwds)
40 # As this already tried the method, subok is maybe quite reasonable here
41 # but this follows what was done before. TODO: revisit this.
42 arr, = conv.as_arrays(subok=False)
---> 43 result = getattr(arr, method)(*args, **kwds)
45 return conv.wrap(result, to_scalar=False)
File ~/checkouts/readthedocs.org/user_builds/pint-pandas/envs/latest/lib/python3.11/site-packages/numpy/_core/_methods.py:113, in _clip(a, min, max, out, **kwargs)
111 return um.maximum(a, min, out=out, **kwargs)
112 else:
--> 113 return um.clip(a, min, max, out=out, **kwargs)
File pandas/_libs/missing.pyx:415, in pandas._libs.missing.NAType.__bool__()
TypeError: boolean value of NA is ambiguous
Apply the function to the PintArray instead of the Series using Series.values.
In [5]: np.clip(df['A'].values, 3 * ureg.m, 5 * ureg.m)
Out[5]:
<PintArray>
[3.0, 3.0, <NA>, 4.0, 5.0]
Length: 5, dtype: pint[meter][Float64]