¿Impresión bonita y fácil de flotadores en Python?

93

Tengo una lista de carrozas. Si simplemente printlo hago , se muestra así:

[9.0, 0.052999999999999999, 0.032575399999999997, 0.010892799999999999, 0.055702500000000002, 0.079330300000000006]

Podría usar print "%.2f", lo que requeriría un forbucle para recorrer la lista, pero luego no funcionaría para estructuras de datos más complejas. Me gustaría algo como (me lo estoy inventando por completo)

>>> import print_options
>>> print_options.set_float_precision(2)
>>> print [9.0, 0.052999999999999999, 0.032575399999999997, 0.010892799999999999, 0.055702500000000002, 0.079330300000000006]
[9.0, 0.05, 0.03, 0.01, 0.06, 0.08]
static_rtti
fuente

Respuestas:

24

Es una pregunta antigua, pero agregaría algo potencialmente útil:

Sé que escribió su ejemplo en listas de Python sin procesar, pero si decide usar numpymatrices en su lugar (lo que sería perfectamente legítimo en su ejemplo, porque parece estar tratando con matrices de números), hay (casi exactamente) este comando que dijiste que te inventaste:

import numpy as np
np.set_printoptions(precision=2)

O incluso mejor en su caso, si aún desea ver todos los decimales de números realmente precisos, pero deshacerse de los ceros finales, por ejemplo, use la cadena de formato %g:

np.set_printoptions(formatter={"float_kind": lambda x: "%g" % x})

Para imprimir una sola vez y no cambiar el comportamiento global, utilice np.array2stringlos mismos argumentos que antes.

PlasmaBinturong
fuente
102

Como nadie lo ha agregado, debe tenerse en cuenta que, a partir de Python 2.6+, la forma recomendada de formatear cadenas es formatprepararse para Python 3+.

print ["{0:0.2f}".format(i) for i in a]

La nueva sintaxis de formateo de cadenas no es difícil de usar y, sin embargo, es bastante poderosa.

Pensé que pprintpodría tener algo, pero no he encontrado nada.

Esteban Küber
fuente
1
Este fue el que usé pero agregué .replace("'", "")para deshacerme de esas comas. str(["{0:0.2f}".format(i) for i in a]).replace("'", "")
Steinarr Hrafn Höskuldsson
Esto producirá una lista de cadenas. En la salida impresa, cada elemento tiene ''a su alrededor. Por ejemplo, a=[0.2222, 0.3333]producirá ['0.22', '0.33'].
jdhao
Para eliminar el vértice y las comas, debe usar' '.join([{0:0.2f}".format(i) for i in a])
Neb
78

Una solución más permanente es la subclase float:

>>> class prettyfloat(float):
    def __repr__(self):
        return "%0.2f" % self

>>> x
[1.290192, 3.0002, 22.119199999999999, 3.4110999999999998]
>>> x = map(prettyfloat, x)
>>> x
[1.29, 3.00, 22.12, 3.41]
>>> y = x[2]
>>> y
22.12

El problema con las subclases floates que rompe el código que busca explícitamente el tipo de variable. Pero por lo que yo sé, ese es el único problema. Y un simple x = map(float, x)deshace la conversión a prettyfloat.

Trágicamente, no se puede simplemente parchear float.__repr__, porque floates inmutable.

Si no desea crear una subclase float, pero no le importa definir una función, map(f, x)es mucho más conciso que[f(n) for n in x]

Robert Rossney
fuente
Hubiera pensado que había una solución más simple, pero tu respuesta es claramente la mejor, ya que eres el único que realmente responde a mi pregunta.
static_rtti
4
Él es el único que realmente responde a su pregunta -editada-. No menospreciar al que responde, pero no puede aclarar una pregunta y luego menospreciar al resto de los que respondieron en función de la información con la que estábamos trabajando.
Jed Smith
1
Mi pregunta original mencionó que consideraba que un bucle for no era una buena solución (para mí, la comprensión de una lista es la misma, pero estoy de acuerdo en que no estaba claro). Intentaré ser más claro la próxima vez.
static_rtti
2
[f (n) para n en x] es mucho más pitónico que map (f, x).
Robert T. McGibbon
2
No estoy necesariamente a favor de subclasificar flotante, pero no creo que la verificación de tipos sea un argumento válido. Al verificar los tipos, se isinstancedebe usar, no la igualdad de type(). Cuando se hace correctamente, una subclase de flotante seguirá contando como flotante.
zondo
37

Tu puedes hacer:

a = [9.0, 0.052999999999999999, 0.032575399999999997, 0.010892799999999999, 0.055702500000000002, 0.079330300000000006]
print ["%0.2f" % i for i in a]
Pablo Santa Cruz
fuente
3
Esto imprimirá ['9.00', '0.05', '0.03', '0.01', '0.06', '0.08'] - con comillas, que generalmente no desea (prefiero tener una lista válida de flotantes impreso)
Emile
23

Tenga en cuenta que también puede multiplicar una cadena como "% .2f" (ejemplo: "% .2f" * 10).

>>> print "%.2f "*len(yourlist) % tuple(yourlist)
2.00 33.00 4.42 0.31 
dalloliogm
fuente
3
¡muy elegante! Me gusta
Nathan Fellman
2
-1 terrible truco. Únase a piezas formateadas de cadenas, no al revés, por favor
u0b34a0f6ae
1
entonces kaizer.se, ¿estás proponiendo "" .join (["%. 2f"% x para x en tu lista]). Tengo que hacer este tipo de construcción en Python.
Gregg Lind
sí, lo propongo, " ".join("%.2f" % x for x in yourlist)ya que separar la cadena de formato y los valores de interpolación es mucho peor que usar un lenguaje feo de Python.
u0b34a0f6ae
Es curiosidad. ¿Por qué la tupla funciona mientras la lista falla? Sin "tupla", comete un error. ¿Por qué?
Joonho Park
8
print "[%s]"%", ".join(map(str,yourlist))

Esto evitará los errores de redondeo en la representación binaria cuando se imprima, sin introducir una restricción de precisión fija (como formatear con "%.2f"):

[9.0, 0.053, 0.0325754, 0.0108928, 0.0557025, 0.0793303]
fortran
fuente
7
l = [9.0, 0.052999999999999999, 0.032575399999999997, 0.010892799999999999, 0.055702500000000002, 0.079330300000000006]

Python 2:

print ', '.join('{:0.2f}'.format(i) for i in l)

Python 3:

print(', '.join('{:0.2f}'.format(i) for i in l))

Salida:

9.00, 0.05, 0.03, 0.01, 0.06, 0.08
Chikipowpow
fuente
No sé por qué esto no es más alto. ¡Una solución que no depende de bibliotecas de terceros!
Fl.pf.
7

La opción más sencilla debería ser utilizar una rutina de redondeo:

import numpy as np
x=[9.0, 0.052999999999999999, 0.032575399999999997, 0.010892799999999999, 0.055702500000000002, 0.079330300000000006]

print('standard:')
print(x)
print("\nhuman readable:")
print(np.around(x,decimals=2))

Esto produce la salida:

standard:
[9.0, 0.053, 0.0325754, 0.0108928, 0.0557025, 0.0793303]

human readable:
[ 9.    0.05  0.03  0.01  0.06  0.08]
Markus Dutschke
fuente
esta es una gran respuesta
jjz
4

Creo que Python 3.1 los imprimirá mejor por defecto, sin ningún cambio de código. Pero eso es inútil si usa extensiones que no se han actualizado para funcionar con Python 3.1

Echo dice reinstalar a Monica
fuente
1
Python 3.1 imprimirá la representación decimal más corta que se corresponda con ese valor flotante. Por ejemplo: >>> a, b = float (1.1), float (1.1000000000000001) >>> a 1.1000000000000001 >>> b 1.1000000000000001 >>> print (a, b) 1.1 1.1
Matt Boehm
4

Las listas de composición son tus amigas.

print ", ".join("%.2f" % f for f in list_o_numbers)

Intentalo:

>>> nums = [9.0, 0.052999999999999999, 0.032575399999999997, 0.010892799999999999]
>>> print ", ".join("%.2f" % f for f in nums)
9.00, 0.05, 0.03, 0.01
Jed Smith
fuente
5
Una expresión generadora sería aún mejor: "," .join ("%. 2f"% f para f en list_o_numbers)
efotinis
@efotinis Todavía no los he agregado a mi repertorio, pero tienes razón, eso es bastante sexy.
Jed Smith
1
@Jed: Por favor, lea la sección de preguntas frecuentes "¿Otras personas pueden editar mis cosas?": Stackoverflow.com/faq . No todas las ediciones son buenas, pero esta fue una mejora genuina. ¿Quizás pueda enumerar ambas técnicas en su respuesta y agregar una nota sobre la diferencia?
Stephan202
4

Para controlar el número de dígitos significativos , utilice el especificador de formato% g.

Vamos a nombrar la solución de Emile prettylist2f. Aquí está el modificado:

prettylist2g = lambda l : '[%s]' % ', '.join("%.2g" % x for x in l)

Uso:

>>> c_e_alpha_eps0 = [299792458., 2.718281828, 0.00729735, 8.8541878e-12]
>>> print(prettylist2f(c_e_alpha_eps0)) # [299792458.00, 2.72, 0.01, 0.00]
>>> print(prettylist2g(c_e_alpha_eps0)) # [3e+08, 2.7, 0.0073, 8.9e-12]

Si desea flexibilidad en la cantidad de dígitos significativos, use el formato de cadena f en su lugar:

prettyflexlist = lambda p, l : '[%s]' % ', '.join(f"{x:.{p}}" for x in l)
print(prettyflexlist(3,c_e_alpha_eps0)) # [3e+08, 2.72, 0.0073, 8.85e-12]
Rainald62
fuente
3

Podrías usar pandas.

A continuación se muestra un ejemplo con una lista:

In: import pandas as P
In: P.set_option('display.precision',3)
In: L = [3.4534534, 2.1232131, 6.231212, 6.3423423, 9.342342423]
In: P.Series(data=L)
Out: 
0    3.45
1    2.12
2    6.23
3    6.34
4    9.34
dtype: float64

Si tiene un dict d y quiere sus claves como filas:

In: d
Out: {1: 0.453523, 2: 2.35423234234, 3: 3.423432432, 4: 4.132312312}

In: P.DataFrame(index=d.keys(), data=d.values())
Out:  
    0
1   0.45
2   2.35
3   3.42
4   4.13

Y otra forma de dar dict a un DataFrame:

P.DataFrame.from_dict(d, orient='index')
ifmihai
fuente
2

Primero, los elementos dentro de una colección imprimen su repr. deberías aprender sobre __repr__y __str__.

Ésta es la diferencia entre print repr (1.1) e print 1.1. Unamos todas esas cadenas en lugar de las representaciones:

numbers = [9.0, 0.053, 0.0325754, 0.0108928, 0.0557025, 0.07933]
print "repr:", " ".join(repr(n) for n in numbers)
print "str:", " ".join(str(n) for n in numbers)
u0b34a0f6ae
fuente
NOTA: En Python 2.7, para este ejemplo, los resultados de la línea "repr" y la línea "str" ​​son idénticos.
ToolmakerSteve
2

Me encontré con este problema al intentar usar pprint para generar una lista de tuplas de flotantes. Las comprensiones anidadas pueden ser una mala idea, pero esto es lo que hice:

tups = [
        (12.0, 9.75, 23.54),
        (12.5, 2.6, 13.85),
        (14.77, 3.56, 23.23),
        (12.0, 5.5, 23.5)
       ]
pprint([['{0:0.02f}'.format(num) for num in tup] for tup in tups])

Usé expresiones de generador al principio, pero pprint simplemente repred el generador ...

kitsu.eb
fuente
2

A partir de Python 3.6, puede usar f-strings:

list_ = [9.0, 0.052999999999999999, 
         0.032575399999999997, 0.010892799999999999, 
         0.055702500000000002, 0.079330300000000006]

print(*[f"{element:.2f}" for element in list_])
#9.00 0.05 0.03 0.01 0.06 0.08

Puede usar parámetros de impresión manteniendo el código muy legible:

print(*[f"{element:.2f}" for element in list_], sep='|', end='<--')
#9.00|0.05|0.03|0.01|0.06|0.08<--
x0s
fuente
1

Tuve este problema, pero ninguna de las soluciones aquí hizo exactamente lo que quería (quiero que la salida impresa sea una expresión de Python válida), entonces, ¿qué tal esto?

prettylist = lambda l : '[%s]' % ', '.join("%.2f" % f for f in l)

Uso:

>>> ugly = [9.0, 0.052999999999999999, 0.032575399999999997,
            0.010892799999999999, 0.055702500000000002, 0.079330300000000006]
>>> prettylist = lambda l : '[%s]' % ', '.join("%.2f" % f for f in l)
>>> print prettylist(ugly)
[9.00, 0.05, 0.03, 0.01, 0.06, 0.08]

(Sé que .format () se supone que es la solución más estándar, pero encuentro esto más legible)

Emile
fuente
0

Estoy de acuerdo con el comentario de SilentGhost, el bucle for no es tan malo. Puedes lograr lo que quieras con:

l = [9.0, 0.052999999999999999, 0.032575399999999997, 0.010892799999999999, 0.055702500000000002, 0.079330300000000006]
for x in l: print "%0.2f" % (x)
PTBNL
fuente
3
Si bien los bucles for no son feos, este uso no es terriblemente Pythonic.
Jed Smith
-1

El siguiente código me funciona bien.

list = map (lambda x: float('%0.2f' % x), list)
Romerito
fuente