¿Cómo hacer una impresión bonita de un numpy.array sin notación científica y con una precisión dada?

Tengo curiosidad por saber si hay alguna forma de imprimir numpy.arrays formateados, por ejemplo, de una manera similar a esto:

 x = 1.23456 print '%.3f' % x 

Si quiero imprimir el numpy.array de una numpy.array de flotadores, imprime varios decimales, a menudo en formato ‘científico’, que es bastante difícil de leer incluso para matrices de baja dimensión. Sin embargo, numpy.array aparentemente tiene que imprimirse como una cadena, es decir, con %s . ¿Existe alguna solucion para esto?

Puede usar set_printoptions para establecer la precisión de la salida:

 import numpy as np x=np.random.random(10) print(x) # [ 0.07837821 0.48002108 0.41274116 0.82993414 0.77610352 0.1023732 # 0.51303098 0.4617183 0.33487207 0.71162095] np.set_printoptions(precision=3) print(x) # [ 0.078 0.48 0.413 0.83 0.776 0.102 0.513 0.462 0.335 0.712] 

Y suppress el uso de la notación científica para números pequeños:

 y=np.array([1.5e-10,1.5,1500]) print(y) # [ 1.500e-10 1.500e+00 1.500e+03] np.set_printoptions(suppress=True) print(y) # [ 0. 1.5 1500. ] 

Vea los documentos para set_printoptions para otras opciones.


Para aplicar las opciones de impresión localmente , utilizando NumPy 1.15.0 o posterior, puede usar el administrador de contexto numpy.printoptions . Por ejemplo, dentro de la precision=3 with-suite precision=3 y suppress=True se establecen:

 x = np.random.random(10) with np.printoptions(precision=3, suppress=True): print(x) # [ 0.073 0.461 0.689 0.754 0.624 0.901 0.049 0.582 0.557 0.348] 

Pero fuera de with-suite las opciones de impresión vuelven a la configuración predeterminada:

 print(x) # [ 0.07334334 0.46132615 0.68935231 0.75379645 0.62424021 0.90115836 # 0.04879837 0.58207504 0.55694118 0.34768638] 

Si está utilizando una versión anterior de NumPy, puede crear usted mismo el administrador de contexto. Por ejemplo,

 import numpy as np import contextlib @contextlib.contextmanager def printoptions(*args, **kwargs): original = np.get_printoptions() np.set_printoptions(*args, **kwargs) try: yield finally: np.set_printoptions(**original) x = np.random.random(10) with printoptions(precision=3, suppress=True): print(x) # [ 0.073 0.461 0.689 0.754 0.624 0.901 0.049 0.582 0.557 0.348] 

Para evitar que los ceros se eliminen del final de las flotaciones:

np.set_printoptions ahora tiene un parámetro de formatter que le permite especificar una función de formato para cada tipo.

 np.set_printoptions(formatter={'float': '{: 0.3f}'.format}) print(x) 

que imprime

 [ 0.078 0.480 0.413 0.830 0.776 0.102 0.513 0.462 0.335 0.712] 

en lugar de

 [ 0.078 0.48 0.413 0.83 0.776 0.102 0.513 0.462 0.335 0.712] 

Unutbu dio una respuesta realmente completa (también obtuvieron un +1 de mi parte), pero aquí hay una alternativa de baja tecnología:

 >>> x=np.random.randn(5) >>> x array([ 0.25276524, 2.28334499, -1.88221637, 0.69949927, 1.0285625 ]) >>> ['{:.2f}'.format(i) for i in x] ['0.25', '2.28', '-1.88', '0.70', '1.03'] 

Como una función (usando la syntax format() para formatear):

 def ndprint(a, format_string ='{0:.2f}'): print [format_string.format(v,i) for i,v in enumerate(a)] 

Uso:

 >>> ndprint(x) ['0.25', '2.28', '-1.88', '0.70', '1.03'] >>> ndprint(x, '{:10.4e}') ['2.5277e-01', '2.2833e+00', '-1.8822e+00', '6.9950e-01', '1.0286e+00'] >>> ndprint(x, '{:.8g}') ['0.25276524', '2.283345', '-1.8822164', '0.69949927', '1.0285625'] 

El índice de la matriz es accesible en la cadena de formato:

 >>> ndprint(x, 'Element[{1:d}]={0:.2f}') ['Element[0]=0.25', 'Element[1]=2.28', 'Element[2]=-1.88', 'Element[3]=0.70', 'Element[4]=1.03'] 

Puede obtener un subconjunto de la funcionalidad np.array_str comando np.array_str , que se aplica solo a una sola statement de impresión.

http://docs.scipy.org/doc/numpy/reference/generated/numpy.array_str.html

Por ejemplo:

 In [27]: x = np.array([[1.1, 0.9, 1e-6]]*3) In [28]: print x [[ 1.10000000e+00 9.00000000e-01 1.00000000e-06] [ 1.10000000e+00 9.00000000e-01 1.00000000e-06] [ 1.10000000e+00 9.00000000e-01 1.00000000e-06]] In [29]: print np.array_str(x, precision=2) [[ 1.10e+00 9.00e-01 1.00e-06] [ 1.10e+00 9.00e-01 1.00e-06] [ 1.10e+00 9.00e-01 1.00e-06]] In [30]: print np.array_str(x, precision=2, suppress_small=True) [[ 1.1 0.9 0. ] [ 1.1 0.9 0. ] [ 1.1 0.9 0. ]] 

La gem que hace que sea muy fácil obtener el resultado como una cadena (en las versiones de hoy en día) está oculta en la respuesta denis: np.array2string

 >>> import numpy as np >>> x=np.random.random(10) >>> np.array2string(x, formatter={'float_kind':'{0:.3f}'.format}) '[0.599 0.847 0.513 0.155 0.844 0.753 0.920 0.797 0.427 0.420]' 

Años después, otro está abajo. Pero para el uso diario acabo

 np.set_printoptions( threshold=20, edgeitems=10, linewidth=140, formatter = dict( float = lambda x: "%.3g" % x )) # float arrays %.3g 

 ''' printf( "... %.3g ... %.1f ...", arg, arg ... ) for numpy arrays too Example: printf( """ x: %.3g A: %.1f s: %s B: %s """, x, A, "str", B ) If `x` and `A` are numbers, this is like `"format" % (x, A, "str", B)` in python. If they're numpy arrays, each element is printed in its own format: `x`: eg [ 1.23 1.23e-6 ... ] 3 digits `A`: [ [ 1 digit after the decimal point ... ] ... ] with the current `np.set_printoptions()`. For example, with np.set_printoptions( threshold=100, edgeitems=3, suppress=True ) only the edges of big `x` and `A` are printed. `B` is printed as `str(B)`, for any `B` -- a number, a list, a numpy object ... `printf()` tries to handle too few or too many arguments sensibly, but this is iffy and subject to change. How it works: numpy has a function `np.array2string( A, "%.3g" )` (simplifying a bit). `printf()` splits the format string, and for format / arg pairs format: % defg arg: try `np.asanyarray()` --> %s np.array2string( arg, format ) Other formats and non-ndarray args are left alone, formatted as usual. Notes: `printf( ... end= file= )` are passed on to the python `print()` function. Only formats `% [optional width . precision] defg` are implemented, not `%(varname)format` . %d truncates floats, eg 0.9 and -0.9 to 0; %.0f rounds, 0.9 to 1 . %g is the same as %.6g, 6 digits. %% is a single "%" character. The function `sprintf()` returns a long string. For example, title = sprintf( "%sm %gn %g X %.3g", __file__, m, n, X ) print( title ) ... pl.title( title ) Module globals: _fmt = "%.3g" # default for extra args _squeeze = np.squeeze # (n,1) (1,n) -> (n,) print in 1 line not n See also: http://docs.scipy.org/doc/numpy/reference/generated/numpy.set_printoptions.html http://docs.python.org/2.7/library/stdtypes.html#string-formatting ''' # http://stackoverflow.com/questions/2891790/pretty-printing-of-numpy-array #............................................................................... from __future__ import division, print_function import re import numpy as np __version__ = "2014-02-03 feb denis" _splitformat = re.compile( r'''( % (? ['...' '%3.0f' '...' '%g' '...' '%-10s' '...'] # odd len, first or last may be "" _fmt = "%.3g" # default for extra args _squeeze = np.squeeze # (n,1) (1,n) -> (n,) print in 1 line not n #............................................................................... def printf( format, *args, **kwargs ): print( sprintf( format, *args ), **kwargs ) # end= file= printf.__doc__ = __doc__ def sprintf( format, *args ): """ sprintf( "text %.3g text %4.1f ... %s ... ", numpy arrays or ... ) %[defg] array -> np.array2string( formatter= ) """ args = list(args) if not isinstance( format, basestring ): args = [format] + args format = "" tf = _splitformat.split( format ) # [ text %e text %f ... ] nfmt = len(tf) // 2 nargs = len(args) if nargs < nfmt: args += (nfmt - nargs) * ["?arg?"] elif nargs > nfmt: tf += (nargs - nfmt) * [_fmt, " "] # default _fmt for j, arg in enumerate( args ): fmt = tf[ 2*j + 1 ] if arg is None \ or isinstance( arg, basestring ) \ or (hasattr( arg, "__iter__" ) and len(arg) == 0): tf[ 2*j + 1 ] = "%s" # %f -> %s, not error continue args[j], isarray = _tonumpyarray(arg) if isarray and fmt[-1] in "defgEFG": tf[ 2*j + 1 ] = "%s" fmtfunc = (lambda x: fmt % x) formatter = dict( float_kind=fmtfunc, int=fmtfunc ) args[j] = np.array2string( args[j], formatter=formatter ) try: return "".join(tf) % tuple(args) except TypeError: # shouldn't happen print( "error: tf %s types %s" % (tf, map( type, args ))) raise def _tonumpyarray( a ): """ a, isarray = _tonumpyarray( a ) -> scalar, False np.asanyarray(a), float or int a, False """ a = getattr( a, "value", a ) # cvxpy if np.isscalar(a): return a, False if hasattr( a, "__iter__" ) and len(a) == 0: return a, False try: # map .value ? a = np.asanyarray( a ) except ValueError: return a, False if hasattr( a, "dtype" ) and a.dtype.kind in "fi": # complex ? if callable( _squeeze ): a = _squeeze( a ) # np.squeeze return a, True else: return a, False #............................................................................... if __name__ == "__main__": import sys n = 5 seed = 0 # run this.py n= ... in sh or ipython for arg in sys.argv[1:]: exec( arg ) np.set_printoptions( 1, threshold=4, edgeitems=2, linewidth=80, suppress=True ) np.random.seed(seed) A = np.random.exponential( size=(n,n) ) ** 10 x = A[0] printf( "x: %.3g \nA: %.1f \ns: %s \nB: %s ", x, A, "str", A ) printf( "x %%d: %d", x ) printf( "x %%.0f: %.0f", x ) printf( "x %%.1e: %.1e", x ) printf( "x %%g: %g", x ) printf( "x %%s uses np printoptions: %s", x ) printf( "x with default _fmt: ", x ) printf( "no args" ) printf( "too few args: %g %g", x ) printf( x ) printf( x, x ) printf( None ) printf( "[]:", [] ) printf( "[3]:", [3] ) printf( np.array( [] )) printf( [[]] ) # squeeze 

FYI Numpy 1.15 (fecha de lanzamiento pendiente) incluirá un administrador de contexto para configurar las opciones de impresión localmente . Esto significa que lo siguiente funcionará de la misma manera que el ejemplo correspondiente en la respuesta aceptada (por unutbu y Neil G) sin tener que escribir su propio administrador de contexto. Ej., Usando su ejemplo:

 x = np.random.random(10) with np.printoptions(precision=3, suppress=True): print(x) # [ 0.073 0.461 0.689 0.754 0.624 0.901 0.049 0.582 0.557 0.348] 

Y aquí está lo que uso, y es bastante sencillo:

 print(np.vectorize("%.2f".__mod__)(sparse)) 

A menudo quiero que diferentes columnas tengan diferentes formatos. Aquí es cómo imprimo una matriz 2D simple utilizando cierta variedad en el formato al convertir (porciones de) mi matriz NumPy en una tupla:

 import numpy as np dat = np.random.random((10,11))*100 # Array of random values between 0 and 100 print(dat) # Lines get truncated and are hard to read for i in range(10): print((4*"%6.2f"+7*"%9.4f") % tuple(dat[i,:])) 

numpy.char.mod también puede ser útil, dependiendo de los detalles de su aplicación, por ejemplo: numpy.char.mod('Value=%4.2f', numpy.arange(5, 10, 0.1)) devolverá una matriz de cadena con los elementos “Valor = 5.00”, “Valor = 5.10”, etc. (como un ejemplo un tanto artificial).

Encuentro que el formato flotante habitual {: 9.5f} funciona correctamente, suprimiendo las notaciones electrónicas de pequeño valor, cuando se muestra una lista o una matriz utilizando un bucle. Pero ese formato a veces no puede suprimir su notación electrónica cuando un formateador tiene varios elementos en una sola statement de impresión. Por ejemplo:

 import numpy as np np.set_printoptions(suppress=True) a3 = 4E-3 a4 = 4E-4 a5 = 4E-5 a6 = 4E-6 a7 = 4E-7 a8 = 4E-8 #--first, display separate numbers----------- print('Case 3: a3, a4, a5: {:9.5f}{:9.5f}{:9.5f}'.format(a3,a4,a5)) print('Case 4: a3, a4, a5, a6: {:9.5f}{:9.5f}{:9.5f}{:9.5}'.format(a3,a4,a5,a6)) print('Case 5: a3, a4, a5, a6, a7: {:9.5f}{:9.5f}{:9.5f}{:9.5}{:9.5f}'.format(a3,a4,a5,a6,a7)) print('Case 6: a3, a4, a5, a6, a7, a8: {:9.5f}{:9.5f}{:9.5f}{:9.5f}{:9.5}{:9.5f}'.format(a3,a4,a5,a6,a7,a8)) #---second, display a list using a loop---------- myList = [a3,a4,a5,a6,a7,a8] print('List 6: a3, a4, a5, a6, a7, a8: ', end='') for x in myList: print('{:9.5f}'.format(x), end='') print() #---third, display a numpy array using a loop------------ myArray = np.array(myList) print('Array 6: a3, a4, a5, a6, a7, a8: ', end='') for x in myArray: print('{:9.5f}'.format(x), end='') print() 

Mis resultados muestran el error en los casos 4, 5 y 6:

 Case 3: a3, a4, a5: 0.00400 0.00040 0.00004 Case 4: a3, a4, a5, a6: 0.00400 0.00040 0.00004 4e-06 Case 5: a3, a4, a5, a6, a7: 0.00400 0.00040 0.00004 4e-06 0.00000 Case 6: a3, a4, a5, a6, a7, a8: 0.00400 0.00040 0.00004 0.00000 4e-07 0.00000 List 6: a3, a4, a5, a6, a7, a8: 0.00400 0.00040 0.00004 0.00000 0.00000 0.00000 Array 6: a3, a4, a5, a6, a7, a8: 0.00400 0.00040 0.00004 0.00000 0.00000 0.00000 

No tengo una explicación para esto y, por lo tanto, siempre uso un bucle para la salida flotante de múltiples valores.

yo suelo

 def np_print(array,fmt="10.5f"): print (array.size*("{:"+fmt+"}")).format(*array) 

No es difícil modificarlo para matrices multidimensionales.

Otra opción más es usar el módulo decimal :

 import numpy as np from decimal import * arr = np.array([ 56.83, 385.3 , 6.65, 126.63, 85.76, 192.72, 112.81, 10.55]) arr2 = [str(Decimal(i).quantize(Decimal('.01'))) for i in arr] # ['56.83', '385.30', '6.65', '126.63', '85.76', '192.72', '112.81', '10.55'] 

Me sorprendió que no viera el método mencionado, lo que significa que no tendrá problemas con las opciones de impresión.

 import numpy as np x = np.random.random([5,5]) print(np.around(x,decimals=3)) Output: [[0.475 0.239 0.183 0.991 0.171] [0.231 0.188 0.235 0.335 0.049] [0.87 0.212 0.219 0.9 0.3 ] [0.628 0.791 0.409 0.5 0.319] [0.614 0.84 0.812 0.4 0.307]] 

Las matrices numpy tienen el método round(precision) que devuelve una nueva matriz numpy con elementos redondeados en consecuencia.

 import numpy as np x = np.random.random([5,5]) print(x.round(3))