Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Numpy engineering notation

Tags:

python

numpy

Is there a way to limit the representation of floating point numbers so that they correspond only to the prefixes used in physical units.

An example will make it clearer:

0.01   ->   currently       1e-02  
       ->   what I'd like   10e-03

0.0001   ->   currently       1e-04  
         ->   what I'd like   100e-06

The motivation behind it is that I'm doing some time measurements and having the representations as representations of 1000 is much more user friendly. I know that 10e-03 -> 10mili or 100e-06 -> 100u

Update

For numpy 1.7< there is a formatter attribute in the set_printoptions(). The solution for which I'm heading for is writing an inline function which would do the formating. Once set, it the formatting should be available globally.

Reference about the formatter

like image 335
TheMeaningfulEngineer Avatar asked Jul 29 '13 17:07

TheMeaningfulEngineer


2 Answers

If helps, a 'solution' can be:

Use ticker.EngFormatter() from matplotlib library together with numpy's set_printoptions. As pointed out by @TheMeaningfulEngineer's update link, it's formatter attribute requires a dict of keys each with a callable value (a function basically). The possible keys are basically the types to apply the format to. Those can be found in numpy's documentation.

Matplolib ticker don't use exponent but SI units (n, μ, k, k, M, etc)

Example:

import numpy as np
from matplotlib import ticker
formatter = ticker.EngFormatter()
np.set_printoptions(formatter={'float': formatter})
np.array([0.0000001, 0.000001, 10, 1000., 10000, 1000000])

which results in:

array([100 n, 1 μ, 10, 1 k, 10 k, 1 M])

For more on how to redefine SI units, I recommend this blog.


Update:

For those interested, matplolib's EngFormatter can accept argument such as units=' Hz', so that after the prefix values are printed with the unit. Like so:

array([100 n Hz, 1 μ Hz, 10  Hz, 1 k Hz, 10 k Hz, 1 M Hz])

Also, same idea can be applied to pandas by overwriting corresponding formatter.

pd.options.display.float_format = formatter
like image 148
Traxidus Wolf Avatar answered Oct 22 '22 15:10

Traxidus Wolf


I think that this topic might be helpful for you. On the other hand, I would try to create a few "buckets" for values in specific ranges and check a simple condition > (lowest value in range), then multiply that value by a range, e.g. 2e-5 by 1e6 to get 20u. Not quite efficient, but easy.

like image 1
akson128 Avatar answered Oct 22 '22 16:10

akson128