2010-05-23 7 views
205

Sono curioso, se non v'è alcun modo per stampare numpy.arrays formattati, ad esempio, in modo simile a questo:Come stampare una matrice numpy.ray senza notazione scientifica e con precisione data?

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

Se voglio stampare il numpy.array dei carri allegorici, stampa diversi decimali, spesso in formato "scientifico", che è piuttosto difficile da leggere anche per gli array a bassa dimensionalità. Comunque, numpy.array apparentemente deve essere stampato come una stringa, cioè con% s. C'è qualche soluzione per questo scopo?

risposta

336

È possibile utilizzare set_printoptions per impostare la precisione dell'output:

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] 

E suppress sopprime l'uso di notazione scientifica per i numeri piccoli:

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. ] 

Vedere la docs for set_printoptions per altre opzioni.


Per applicare le opzioni di stampa a livello locale, è possibile utilizzare un contextmanager:

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) 

Ad esempio, all'interno della with-suiteprecision=3 e suppress=True sono impostati:

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] 

Ma al di fuori del with-suite le opzioni di stampa tornano alle impostazioni predefinite:

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

Per evitare zeri vengano rimossi dalla fine dei carri:

np.set_printoptions ora ha un parametro formatter che consente di specificare una funzione di formato per ogni tipo.

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

che stampa

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

invece di

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

c'è un mezzo t o applicare la formattazione solo alla specifica istruzione di stampa (anziché impostare un formato di output generale utilizzato da * all * print statements)? – bph

+5

@Hiett: non esiste una funzione NumPy per impostare le opzioni di stampa per un solo 'print', ma è possibile utilizzare un gestore di contesto per creare qualcosa di simile. Ho modificato il post in alto per mostrare cosa intendo. – unutbu

+7

+1 per il contesto direttore – fotNelton

29

Unutbu ha dato una risposta davvero completa (hanno ottenuto un +1 anche da me), ma qui è un'alternativa lo-Tech :

>>> 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'] 

Come una funzione (Utilizzando la sintassi format() per la formattazione):

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

utilizzati:

>>> 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'] 

L'indice dell'array è accessibile nella stringa di 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'] 
5

anni più tardi, un altro è sotto. Ma per l'uso quotidiano ho appena

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`: e.g. [ 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: % d e f g 
    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] d e f g` are implemented, 
not `%(varname)format` . 

%d truncates floats, e.g. 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("%s m %g n %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'''(
    % 
    (?<! %%) # not %% 
    -? [ \d . ]* # optional width.precision 
    \w 
    )''', re.X) 
    # ... %3.0f ... %g ... %-10s ... 
    # -> ['...' '%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 
6

Ed ecco quello che io uso, ed è abbastanza semplice:

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

numpy.char.mod può anche essere utile, a seconda delle particolari della vostra l'applicazione ad esempio: numpy.char.mod('Value=%4.2f', numpy.arange(5, 10, 0.1)) restituirà un array di stringhe con elementi "Value = 5.00", "Value = 5.10" ecc. (come un esempio un po 'forzato).

25

È possibile ottenere un sottoinsieme della funzionalità np.set_printoptions dal comando np.array_str, che si applica solo a una singola istruzione di stampa.

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

Ad esempio:

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. ]] 
2

ho spesso vogliono diverse colonne di avere diversi formati. Ecco come si stampa una matrice 2D semplice usando una certa varietà nella formattazione convertendo (fette di) mia matrice NumPy ad 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,:])) 
9

La gemma che lo rende fin troppo facile per ottenere il risultato come una stringa (nelle versioni NumPy di ​​oggi) è nascosto in denis risposta: 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]' 
0

un'altra opzione è quella di utilizzare il modulo 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'] 
Problemi correlati