Skip to content

Commit

Permalink
Pr/137 compat check (#245)
Browse files Browse the repository at this point in the history
* _get_common_dtype must check PintTypes compat

PR number 137 adds _get_common_dtype to PintType so that `PintType` operations can be performed on a mix of `PintType` and numeric values (with the later being promoted to the `PintType` for the purposes of the operation).  However, when there are multiple `PintType` elements present, it is important that all elements are in fact compatible, lest the operation attempt to combine two `PintType` elements that are not unit-compatible.

* Fix pre-commit and add CHANGES

Clean up PR for submission.

* Update CHANGES

* Update pint_array.py

* fix issue

---------

Co-authored-by: andrewgsavage <[email protected]>
  • Loading branch information
MichaelTiemannOSC and andrewgsavage committed Jul 29, 2024
1 parent f205835 commit 1943f2b
Show file tree
Hide file tree
Showing 3 changed files with 47 additions and 4 deletions.
4 changes: 2 additions & 2 deletions CHANGES
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@ pint-pandas Changelog
=====================


0.7 (unreleased)
0.6.2 (2024-07-29)
--------------------

- Nothing added yet.
- Fix PintType._get_common_dtype (added via #137) to check compatibility of all `PintType`s in `dtypes`


0.6.1 (2024-07-13)
Expand Down
13 changes: 11 additions & 2 deletions pint_pandas/pint_array.py
Original file line number Diff line number Diff line change
Expand Up @@ -201,8 +201,9 @@ def _get_common_dtype(self, dtypes):
If this function is called this means at least on of the ``dtypes``
list is a ``PintType``
In order to be able to be able to perform operation on ``PintType``
In order to be able to perform operation on ``PintType``
with scalars, mix of ``PintType`` and numeric values are allowed.
But all ``PintType`` elements must be compatible.
Parameters
Expand All @@ -213,10 +214,18 @@ def _get_common_dtype(self, dtypes):
-------
returns self for acceptable cases or None otherwise
"""
# Return self (PintType with same units) if possible
if all(
isinstance(x, PintType) or pd.api.types.is_numeric_dtype(x) for x in dtypes
isinstance(dtype, PintType) and dtype.units == self.units
for dtype in dtypes
):
return self
# Otherwise return PintType with undefined units
elif all(
isinstance(dtype, PintType) or pd.api.types.is_numeric_dtype(dtype)
for dtype in dtypes
):
return PintType
else:
return None

Expand Down
34 changes: 34 additions & 0 deletions pint_pandas/testsuite/test_issues.py
Original file line number Diff line number Diff line change
Expand Up @@ -277,3 +277,37 @@ def test_eval(self):
)
tm.assert_series_equal(df.eval("a / b"), df["a"] / df["b"])
tm.assert_series_equal(df.eval("a / c"), df["a"] / df["c"])
tm.assert_series_equal(df.eval("a / a"), df["a"] / df["a"])

def test_mixed_df(self):
df = pd.DataFrame(
{
"a": pd.Series([1.0, 2.0, 3.0], dtype="pint[meter]"),
"b": pd.Series([4.0, 5.0, 6.0], dtype="pint[second]"),
"c": [1.0, 2.0, 3.0],
}
)

assert df["a"][0] == df.iloc[0, 0]


class TestIssue246(BaseExtensionTests):
def test_issue246(self):
df = pd.DataFrame(
{
"a": [1, 2, 3],
"b": [4, 5, 6],
"c": [7, 8, 9],
}
)

df = df.astype(
{
"a": "pint[m]",
"b": "pint[m/s]",
"c": "pint[kN]",
}
)

# now an operation where each cell is independent from each other
df.apply(lambda x: x * 2, axis=1)

0 comments on commit 1943f2b

Please sign in to comment.