Skip to content

Commit

Permalink
subdtype
Browse files Browse the repository at this point in the history
  • Loading branch information
andrewgsavage committed Jul 31, 2024
1 parent a20e0d7 commit 9e47e7a
Show file tree
Hide file tree
Showing 4 changed files with 29 additions and 29 deletions.
26 changes: 13 additions & 13 deletions pint_pandas/pint_array.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,9 @@ class PintType(ExtensionDtype):
# base = np.dtype('O')
# num = 102
units: Optional[_Unit] = None # Filled in by `construct_from_..._string`
_metadata = ("units",)
_match = re.compile(r"(P|p)int\[(?P<units>.+)\]")
subdtype: Optional[np.dtype] = None
_metadata = ("units","subdtype")
_match = re.compile(r"(P|p)int\[(?P<units>.+)\]\[(?P<subdtype>.+)\]")
_cache = {} # type: ignore
ureg = pint.get_application_registry()

Expand Down Expand Up @@ -145,7 +146,7 @@ def construct_from_quantity_string(cls, string):

@property
def name(self):
return str("pint[{units}]".format(units=self.units))
return str("pint[{units}][{subdtype}]".format(units=self.units, subdtype=self.subdtype))

@property
def na_value(self):
Expand All @@ -160,6 +161,7 @@ def __eq__(self, other):
other = PintType(other)
except (ValueError, errors.UndefinedUnitError):
return False
print(self.units, other.units)
return self.units == other.units

@classmethod
Expand Down Expand Up @@ -288,32 +290,30 @@ class PintArray(ExtensionArray, ExtensionScalarOpsMixin):
_HANDLED_TYPES = (np.ndarray, numbers.Number, _Quantity)

def __init__(self, values, dtype=None, copy=False):
# infer dtype from values if not given
if dtype is None:
if isinstance(values, _Quantity):
dtype = values.units
elif isinstance(values, PintArray):
dtype = values._dtype

if dtype is None:
raise NotImplementedError

if not isinstance(dtype, PintType):
dtype = PintType(dtype)
self._dtype = dtype

# convert units if unit aware values
if isinstance(values, _Quantity):
values = values.to(dtype.units).magnitude
elif isinstance(values, PintArray):
values = values._data
if isinstance(values, np.ndarray):
dtype = values.dtype
if dtype in ddtypemap:
dtype = ddtypemap[dtype]
values = pd.array(values, copy=copy, dtype=dtype)
copy = False
elif not isinstance(values, pd.core.arrays.numeric.NumericArray):
values = pd.array(values, copy=copy)
if copy:
values = values.copy()

# convert subdtype
if not isinstance(values, ExtensionArray) or not values.dtype == dtype:
values = pd.array(values, copy=copy, dtype=dtype.subdtype)

self._data = values
self._Q = self.dtype.ureg.Quantity

Expand Down
20 changes: 10 additions & 10 deletions pint_pandas/testsuite/test_issues.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ def test_force_ndarray_like(self):

result = pd.concat([a, b], axis=1)
expected = pd.DataFrame(
{0: PintArray(q_a_), 1: PintArray(q_b)}, dtype="pint[degC]"
{0: PintArray(q_a_), 1: PintArray(q_b)}, dtype="pint[degC][float]"
)
tm.assert_equal(result, expected)

Expand All @@ -64,7 +64,7 @@ def test_offset_concat(self):

result = pd.concat([a, b], axis=1)
expected = pd.DataFrame(
{0: PintArray(q_a_), 1: PintArray(q_b)}, dtype="pint[degC]"
{0: PintArray(q_a_), 1: PintArray(q_b)}, dtype="pint[degC][float]"
)
tm.assert_equal(result, expected)

Expand Down Expand Up @@ -99,8 +99,8 @@ def _timeit(fun, n_runs=5):
@staticmethod
def _make_df(size, pint_units=True, dtype=float):
if pint_units:
dist_unit = "pint[m]"
time_unit = "pint[s]"
dist_unit = "pint[m][float]"
time_unit = "pint[s][float]"
else:
dist_unit = dtype
time_unit = dtype
Expand Down Expand Up @@ -168,23 +168,23 @@ def test_issue_88():


def test_issue_127():
a = PintType.construct_from_string("pint[dimensionless]")
b = PintType.construct_from_string("pint[]")
a = PintType.construct_from_string("pint[dimensionless][float]")
b = PintType.construct_from_string("pint[][float]")
assert a == b


class TestIssue174(BaseExtensionTests):
def test_sum(self):
if pandas_version_info < (2, 1):
pytest.skip("Pandas reduce functions strip units prior to version 2.1.0")
a = pd.DataFrame([[0, 1, 2], [3, 4, 5]]).astype("pint[m]")
a = pd.DataFrame([[0, 1, 2], [3, 4, 5]]).astype("pint[m][float]")
row_sum = a.sum(axis=0)
expected_1 = pd.Series([3, 5, 7], dtype="pint[m]")
expected_1 = pd.Series([3, 5, 7], dtype="pint[m][float]")

tm.assert_series_equal(row_sum, expected_1)

col_sum = a.sum(axis=1)
expected_2 = pd.Series([3, 12], dtype="pint[m]")
expected_2 = pd.Series([3, 12], dtype="pint[m][float]")

tm.assert_series_equal(col_sum, expected_2)

Expand Down Expand Up @@ -303,7 +303,7 @@ def test_issue246(self):

df = df.astype(
{
"a": "pint[m]",
"a": "pint[m][float]",
"b": "pint[m/s]",
"c": "pint[kN]",
}
Expand Down
2 changes: 1 addition & 1 deletion pint_pandas/testsuite/test_pandas_extensiontests.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ def box_in_series(request):

@pytest.fixture
def dtype():
return PintType("pint[meter]")
return PintType("pint[meter][float]")


_base_numeric_dtypes = [float, int]
Expand Down
10 changes: 5 additions & 5 deletions pint_pandas/testsuite/test_pandas_interface.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,8 @@ def test_initialisation(self, data):
# works with PintArray
df = pd.DataFrame(
{
"length": pd.Series([2.0, 3.0], dtype="pint[m]"),
"width": PintArray([2.0, 3.0], dtype="pint[m]"),
"length": pd.Series([2.0, 3.0], dtype="pint[m][float]"),
"width": PintArray([2.0, 3.0], dtype="pint[m][float]"),
"distance": PintArray([2.0, 3.0], dtype="m"),
"height": PintArray([2.0, 3.0], dtype=ureg.m),
"depth": PintArray.from_1darray_quantity(
Expand All @@ -58,8 +58,8 @@ def test_df_operations(self):
# simply a copy of what's in the notebook
df = pd.DataFrame(
{
"torque": pd.Series([1.0, 2.0, 2.0, 3.0], dtype="pint[lbf ft]"),
"angular_velocity": pd.Series([1.0, 2.0, 2.0, 3.0], dtype="pint[rpm]"),
"torque": pd.Series([1.0, 2.0, 2.0, 3.0], dtype="pint[lbf ft][float]"),
"angular_velocity": pd.Series([1.0, 2.0, 2.0, 3.0], dtype="pint[rpm][float]"),
}
)

Expand Down Expand Up @@ -423,7 +423,7 @@ def test_mismatched_dimensions(self):
op(x, y)

def test_numpy_data(self):
foo = PintArray([1, 2, 3], dtype="pint[m]")
foo = PintArray([1, 2, 3], dtype="pint[m][float]")
result = foo.numpy_data
expected = np.array([1, 2, 3], dtype="int64")
np.testing.assert_array_equal(result, expected, strict=True)

0 comments on commit 9e47e7a

Please sign in to comment.