Pint: How to convert units in one dimension, leaving other dimensions unchanged?

Question:

I’d like to normalize measurements of different timespans to per-annum:

import pint
from pint import get_application_registry
ureg = get_application_registry()

x = ureg('kg/d')
print(f"x = {x}")
# x = 1.0 kilogram / d
print(f"x = {x.to('kg/a')}")
# x = 365.2499999999999 kilogram / a

# QUESTION: how do I manipulate x to just change the time dimension to '/a' regardless of other dimensions, resulting in kg/a (in this case)?

I tried reading the documentation, but it does not appear straightforward. I have also looked at similar questions, but they do not apply.

Asked By: Michael Tiemann

||

Answers:

One way to go would be to multiply by the number of days in a year ureg("a").to("d"), then divide by ureg("a") to obtain the result per year:

x = ureg('kg/d')
print(f"x = {x * ureg('a').to('d') / ureg('a')}")
# x = 365.2499999999999 kilogram / year

x = ureg('m**3/d')
print(f"x = {x * ureg('a').to('d') / ureg('a')}")
# x = 365.2499999999999 meter ** 3 / year

Update: finding the unit with the time^-1 dimensionality

Although this is probably not the most straightforward way to do it, one could filter the dict returned by the pint.util.to_units_container function:

def required_dimensionality(unit, exp):
    return ureg(unit).is_compatible_with("s") and exp == -1

x = ureg("kg/d")
unit_ct = pint.util.to_units_container(x)
print(unit_ct)
# <UnitsContainer({'day': -1, 'kilogram': 1})>
time_unit = next(pint.Unit(unit) for unit, exp in unit_ct.items() if required_dimensionality(unit, exp))
print(time_unit)
# <Unit('day')>

Then you can use this to convert to /a as above:
x * ureg('a').to(time_unit) / ureg('a').

Answered By: ИΛJΛ
Categories: questions Tags: ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.