开发者

python - pretty print errorbars

I'm using python with numpy, scipy and matplotlib for data evaluation. As results I obtain averages and fitting parameters with errorbars.

I would like python to automatically pretty-print this data according to a given precision. For example:

Suppose I got the result x = 0.012345 +/- 0.000123. Is there a way to automatically format this as 1.235(12) x 10^-2 when a precision of 2 was specified. That is, counting the precision in the errorbar, rather than in the value.

Does anyone know a package that provides such functionality, or would I have to implement this myself?

Is there a way to inject this into the python string formatting mechanism? I.e. being able to write something like "%.2N" % (0.012345, 0.0000123).

I already looked through the docs of numpy and scipy and googled around, but I couldn't find anything. I think this would be a useful feature for everyone who deals with statistics.

Thanks for your help!

EDIT: As requested by Nathan Whitehead I'll give a few examples.

123 +- 1         ----precision 1----->  123(1)
123 +- 1.1       ----precision 2----->  123.0(11)
0.0123 +- 0.001  ----precision 1----->  0.012(1)
123.111 +- 0.123 ----precision 2----->  123.11(12)

The powers of ten are omitted for clarity. The number inside the parenthesis is a shorthand notation for the standard error. The last digit of the number before the parens and the last digit of the number inside the parens have to be at the same decimal power. For some reason I cannot find a good explanation of this concept online. Only thing I got is this German Wikpedia article here. However, it is a quite common and very handy notation.

EDIT2: I implemented the shorthand notation thing myself:

#!/usr/bin/env python
# *-* coding: utf-8 *-*

from math import floor, log10

# uncertainty to string
def un2str(x, xe, precision=2):
    """pretty print nominal value and uncertainty

    x  - nominal value
    xe - uncertainty
    precision - number of significant digits in uncertainty

    returns shortest string representation of `x +- xe` either as
        x.xx(ee)e+xx
    or as
        xxx.xx(ee)"""
    # base 10 exponents
    x_exp = int(floor(log10(x)))
    xe_exp = int(floor(log10(xe)))

    # uncertainty
    un_exp = xe_exp-precision+1
    un_int = round(xe*10**(-un_exp))

    # nominal value
    no_exp = un_exp
    no_int = round(x*10**(-no_exp))

    # format - nom(unc)exp
    fieldw = x_exp - no_exp
    fmt = '%%.%df' % fieldw
    result1 = (fmt + '(%.0f)e%d') % (no_int*10**(-fieldw), un_int, x_exp)

    # format - nom(unc)
    fieldw = max(0, -no_exp)
    fmt = '%%.%df' % fieldw
    result2 = (fmt + '(%.0f)') % (no_int*10**no_exp, un_int*10**max(0, un_exp))

    # return shortest representation
    if len(result2) <= len(result1):
        return result2
    else:
        return result1


if __name__ == "__main__开发者_C百科":
    xs    = [123456, 12.34567, 0.123456, 0.001234560000, 0.0000123456]
    xes   = [   123,  0.00123, 0.000123, 0.000000012345, 0.0000001234]
    precs = [     1,        2,        3,              4,            1]

    for (x, xe, prec) in zip(xs, xes, precs):
        print '%.6e +- %.6e @%d --> %s' % (x, xe, prec, un2str(x, xe, prec))

Output:

1.234560e+05 +- 1.230000e+02 @1 --> 1.235(1)e5
1.234567e+01 +- 1.230000e-03 @2 --> 12.3457(12)
1.234560e-01 +- 1.230000e-04 @3 --> 0.123456(123)
1.234560e-03 +- 1.234500e-08 @4 --> 0.00123456000(1235)
1.234560e-05 +- 1.234000e-07 @1 --> 1.23(1)e-5


For people that are still interested in this question, see the gvar library and here for an example of (at last part of) the desired behavior by the OP.


since x +- y is not a standard type (it could be seen as a complex with real and imaginary as x and y i guess, but that does not simplify anything...) but you can get full control over the presentation by creating a type and overriding the string function, i.e. something like this

class Res(object):
   def __init__(self, res, delta):
     self.res = res
     self.delta = delta

   def __str__(self):
     return "%f +- %f"%(self.res,self.delta)

if __name__ == '__main__':
   x = Res(0.2710,0.001)
   print(x)
   print(" a result: %s" % x)

you could naturally do something a bit more fancy inside the __str__ function...

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜