Skip to content

Commit e1998e7

Browse files
authored
allow passing a format string to dequantify (#49)
* check that the unit formatting util works correctly * use a format instead of casting to str * allow passing a format to .pint.dequantify * handle empty string formats * move the implementation of dequantify to a shared function * also test a empty string formatter * actually use the format * add a entry to whats-new.rst
1 parent e688dcc commit e1998e7

File tree

3 files changed

+38
-8
lines changed

3 files changed

+38
-8
lines changed

docs/whats-new.rst

+2
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ What's new
99
- allow converting indexes (except :py:class:`pandas.MultiIndex`) (:pull:`56`)
1010
- document the reason for requiring the ``force_ndarray_like`` or ``force_ndarray``
1111
options on unit registries (:pull:`59`)
12+
- allow passing a format string to :py:meth:`Dataset.pint.dequantify` and
13+
:py:meth:`DataArray.pint.dequantify` (:pull:`49`)
1214

1315
v0.1 (October 26 2020)
1416
----------------------

pint_xarray/accessors.py

+18-7
Original file line numberDiff line numberDiff line change
@@ -77,9 +77,11 @@ def merge_mappings(first, *mappings):
7777
return result
7878

7979

80-
def units_to_str_or_none(mapping):
80+
def units_to_str_or_none(mapping, unit_format):
81+
formatter = str if not unit_format else lambda v: unit_format.format(v)
82+
8183
return {
82-
key: str(value) if isinstance(value, Unit) else value
84+
key: formatter(value) if isinstance(value, Unit) else value
8385
for key, value in mapping.items()
8486
}
8587

@@ -241,7 +243,7 @@ def quantify(self, units=None, unit_registry=None, **unit_kwargs):
241243
conversion.attach_units, units
242244
)
243245

244-
def dequantify(self):
246+
def dequantify(self, format=None):
245247
"""
246248
Removes units from the DataArray and its coordinates.
247249
@@ -253,15 +255,19 @@ def dequantify(self):
253255
dequantified : DataArray
254256
DataArray whose array data is unitless, and of the type
255257
that was previously wrapped by `pint.Quantity`.
258+
format : str, optional
259+
The format used for the string representations.
256260
"""
257-
258261
units = conversion.extract_unit_attributes(self.da)
259262
units.update(conversion.extract_units(self.da))
260263

264+
unit_format = f"{{:{format}}}" if isinstance(format, str) else format
265+
266+
units = units_to_str_or_none(units, unit_format)
261267
return (
262268
self.da.pipe(conversion.strip_units)
263269
.pipe(conversion.strip_unit_attributes)
264-
.pipe(conversion.attach_unit_attributes, units_to_str_or_none(units))
270+
.pipe(conversion.attach_unit_attributes, units)
265271
)
266272

267273
@property
@@ -504,7 +510,7 @@ def quantify(self, units=None, unit_registry=None, **unit_kwargs):
504510
conversion.attach_units, units
505511
)
506512

507-
def dequantify(self):
513+
def dequantify(self, format=None):
508514
"""
509515
Removes units from the Dataset and its coordinates.
510516
@@ -516,14 +522,19 @@ def dequantify(self):
516522
dequantified : Dataset
517523
Dataset whose data variables are unitless, and of the type
518524
that was previously wrapped by ``pint.Quantity``.
525+
format : str, optional
526+
The format used for the string representations.
519527
"""
520528
units = conversion.extract_unit_attributes(self.ds)
521529
units.update(conversion.extract_units(self.ds))
522530

531+
unit_format = f"{{:{format}}}" if isinstance(format, str) else format
532+
533+
units = units_to_str_or_none(units, unit_format)
523534
return (
524535
self.ds.pipe(conversion.strip_units)
525536
.pipe(conversion.strip_unit_attributes)
526-
.pipe(conversion.attach_unit_attributes, units_to_str_or_none(units))
537+
.pipe(conversion.attach_unit_attributes, units)
527538
)
528539

529540
def to(self, units=None, **unit_kwargs):

pint_xarray/tests/test_accessors.py

+18-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
from pint.errors import UndefinedUnitError
77
from xarray.testing import assert_equal
88

9-
from .. import conversion
9+
from .. import accessors, conversion
1010
from .utils import raises_regex
1111

1212
pytestmark = [
@@ -101,6 +101,23 @@ def test_parse_integer_inverse(self):
101101
assert result.pint.units == Unit("1 / meter")
102102

103103

104+
@pytest.mark.parametrize("formatter", ("", "P", "C"))
105+
@pytest.mark.parametrize("flags", ("", "~", "#", "~#"))
106+
def test_units_to_str_or_none(formatter, flags):
107+
unit_format = f"{{:{flags}{formatter}}}"
108+
unit_attrs = {None: "m", "a": "s", "b": "degC", "c": "degF", "d": "degK"}
109+
units = {key: unit_registry.Unit(value) for key, value in unit_attrs.items()}
110+
111+
expected = {key: unit_format.format(value) for key, value in units.items()}
112+
actual = accessors.units_to_str_or_none(units, unit_format)
113+
114+
assert expected == actual
115+
assert units == {key: unit_registry.Unit(value) for key, value in actual.items()}
116+
117+
expected = {None: None}
118+
assert expected == accessors.units_to_str_or_none(expected, unit_format)
119+
120+
104121
class TestDequantifyDataArray:
105122
def test_strip_units(self, example_quantity_da):
106123
result = example_quantity_da.pint.dequantify()

0 commit comments

Comments
 (0)