2011-07-12 15 views
7

Estoy usando python con numpy, scipy y matplotlib para la evaluación de datos. Como resultados, obtengo promedios y parámetros de ajuste con barras de error.python - bonitas barras de error de impresión

Me gustaría que python imprima automáticamente esta información según una precisión dada. Por ejemplo:

Supongamos que obtengo el resultado x = 0./- 0.000123. ¿Hay alguna manera de formatear automáticamente esto como 1.235(12) x 10^-2 cuando se especificó una precisión de 2? Es decir, contar la precisión en la barra de errores, en lugar de en el valor.

¿Alguien conoce un paquete que proporcione dicha funcionalidad, o tendría que implementarlo yo mismo?

¿Hay alguna manera de insertar esto en el mecanismo de formato de cadenas de python? Es decir. pudiendo escribir algo como "%.2N" % (0., 0.0000123).

Ya miré a través de los documentos de numpy y scipy y busqué en Google, pero no pude encontrar nada. Creo que esta sería una característica útil para todos los que se ocupan de las estadísticas.

Gracias por su ayuda!

EDITAR: Según lo solicitado por Nathan Whitehead, daré algunos ejemplos.

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

Las potencias de diez se han omitido para mayor claridad. El número dentro del paréntesis es una notación abreviada del error estándar. El último dígito del número antes de los parens y el último dígito del número dentro de los parens debe tener la misma potencia decimal. Por alguna razón, no puedo encontrar una buena explicación de este concepto en línea. Lo único que obtuve es este artículo de Wikpedia en alemán here. Sin embargo, es una notación bastante común y muy útil.

Edit2: implementé la cosa notación abreviada a mí mismo:

#!/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__": 
    xs = [123456, 12.34567, 0.123456, 0.0, 0.000] 
    xes = [ 123, 0.00123, 0.000123, 0.000000, 0.00000] 
    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)) 

Salida:

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.0(1235) 
1.234560e-05 +- 1.234000e-07 @1 --> 1.23(1)e-5 
+1

Podría dar más ejemplos? No entiendo qué significa '1.235 (12) x 10^-2' y cómo se conecta con' 0.' y '0.000123'. –

+0

Claro, '1.235 (12) x 10^-2' es una notación abreviada para' 1.235 x 10^-2 + - 0.0012 x 10^-2'. El número original '0.' se redondea debido a la precisión especificada de 2 en el error estándar. El número '0,000123' es el error estándar de mi resultado. Agregaré algunos ejemplos más a la publicación original. – Lemming

Respuesta

2

desde x +- y no es un tipo estándar (que podría ser visto como un complejo con real e imaginaria como x y yi supongo, pero eso no simplifica nada ...) pero puede obtener un control total sobre la presentación creando un tipo y anulando la función de cadena, es decir, algo como esto

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) 

que, naturalmente, podría hacer algo un poco más sofisticado por dentro la función __str__ ...

+0

Gracias, eso es un comienzo para la parte de cadena de formato. ¿Conoces una manera de pasar argumentos? Es decir. en ''% .4f'' el' .4'. Implementé la notación abreviada yo mismo, vea EDIT2. – Lemming

+0

hola, sí, esa es probablemente la mejor solución para escribir su propia impresora bonita. – bjarneh

+0

lo siento, no he leído su respuesta completamente allí, sí, también puede hacer cadenas de formato dinámicamente, 'fmstr ="% .df "% (somenumber)' si el 'somenumber' se basa en el número de dígitos en' + - 'parte, esto debería funcionar como quieras, creo – bjarneh

Cuestiones relacionadas