Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to define and use percentage in Pint

I'm currently using Pint to handle units and unit conversions. This seems to work well for the units that are already defined in Pint, for example

>>> import pint
>>> ureg = pint.UnitRegistry()
>>> Q = ureg.Quantity
>>> a = Q(5, 'm/s')
>>> a
<Quantity(5, 'meter / second')>
>>> a.to('ft/s')
<Quantity(16.404199475065617, 'foot / second')>

I tried to define my own units, which represent percentage. As far as unit conversions go, a percentage is simply 100 times a dimensionless fraction, which is how I defined it.

>>> ureg.define('percent = dimensionless * 100 = pct')
>>> a = Q(5, 'pct')
>>> a
<Quantity(5, 'percent')>

However I cannot seem to convert back and forth between fraction ('dimensionless') and 'pct'.

>>> a.to('dimensionless')
Traceback (most recent call last):
  File "<pyshell#31>", line 1, in <module>
    a.to('dimensionless')
  File "C:\Python35\python-3.5.1.amd64\lib\site-packages\pint\quantity.py", line 263, in to
    magnitude = self._convert_magnitude_not_inplace(other, *contexts, **ctx_kwargs)
  File "C:\Python35\python-3.5.1.amd64\lib\site-packages\pint\quantity.py", line 231, in _convert_magnitude_not_inplace
    return self._REGISTRY.convert(self._magnitude, self._units, other)
  File "C:\Python35\python-3.5.1.amd64\lib\site-packages\pint\unit.py", line 1026, in convert
    return self._convert(value, src, dst, inplace)
  File "C:\Python35\python-3.5.1.amd64\lib\site-packages\pint\unit.py", line 1042, in _convert
    src_dim = self._get_dimensionality(src)
  File "C:\Python35\python-3.5.1.amd64\lib\site-packages\pint\unit.py", line 813, in _get_dimensionality
    self._get_dimensionality_recurse(input_units, 1.0, accumulator)
  File "C:\Python35\python-3.5.1.amd64\lib\site-packages\pint\unit.py", line 837, in _get_dimensionality_recurse
    self._get_dimensionality_recurse(reg.reference, exp2, accumulator)
  File "C:\Python35\python-3.5.1.amd64\lib\site-packages\pint\unit.py", line 835, in _get_dimensionality_recurse
    reg = self._units[self.get_name(key)]
KeyError: ''

What I'd essentially like to do is be able to convert between e.g. "0.73" and "73%". How can I define and use such a unit?

like image 808
Cory Kramer Avatar asked Aug 25 '16 20:08

Cory Kramer


People also ask

What does pint do in Python?

Pint is Python package to define, operate and manipulate physical quantities: the product of a numerical value and a unit of measurement. It allows arithmetic operations between them and conversions from and to different units. It is distributed with a comprehensive list of physical units, prefixes and constants.

How do you write units in Python?

To assign a unit to a quantity, multiply by the unit, e.g. my_length = 100 * mm. (In normal text you would write “100 mm”, but unfortunately Python does not have “implied multiplication”.)


2 Answers

It seems that GitHub issue hgrecco/pint#185 covers the case you're describing.

Using the work-around discussed in that issue works for me using Pint-0.7.2:

from pint.unit import ScaleConverter
from pint.unit import UnitDefinition
import pint

ureg = pint.UnitRegistry()
Q = ureg.Quantity

ureg.define(UnitDefinition('percent', 'pct', (), ScaleConverter(1 / 100.0)))
a = Q(5, 'pct')

print a
print a.to('dimensionless')

Output:

5 percent
0.05 dimensionless
like image 150
Lukas Graf Avatar answered Nov 07 '22 22:11

Lukas Graf


I had the same problem, and came up with a simple solution which seems to work well.

import pint

ureg = pint.UnitRegistry()
ureg.define('fraction = [] = frac')
ureg.define('percent = 1e-2 frac = pct')
ureg.define('ppm = 1e-6 fraction')

print(ureg('100 pct').to('dimensionless'))
print(ureg('0.5 dimensionless').to('pct'))
print(ureg('pct').to('ppm'))
print(ureg('1e4 ppm').to('pct'))

Output:

1.0 dimensionless
50.0 percent
10000.0 ppm
0.9999999999999999 percent

(Note slight rounding error on last line.)

I got the syntax from the default units dictionary, where base units are defined like

# reference
gram = [mass] = g  # dimensional
radian = [] = rad  # dimensionless
like image 39
GeoMatt22 Avatar answered Nov 07 '22 20:11

GeoMatt22