2010-05-23 4 views
205

Je suis curieux, s'il y a un moyen d'imprimer au format numpy.arrays, par exemple, de la même manière à ceci:Comment jolimer un numpy.array sans notation scientifique et avec une précision donnée?

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

Si je veux imprimer le numpy.array des flotteurs, il imprime plusieurs décimales, souvent dans un format «scientifique», qui est plutôt difficile à lire, même pour des tableaux de faible dimension. Cependant, numpy.array doit apparemment être imprimé en tant que chaîne, c'est-à-dire avec% s. Y a-t-il une solution à cet effet?

Répondre

336

Vous pouvez utiliser set_printoptions pour régler la précision de la sortie:

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] 

Et suppress supprime l'utilisation de la notation scientifique pour un petit nombre:

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

Voir la docs for set_printoptions pour d'autres options.


Pour appliquer les options d'impression localement, vous pouvez utiliser 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) 

Par exemple, à l'intérieur du with-suiteprecision=3 et suppress=True sont fixés:

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] 

Mais en dehors de la with-suite Les options d'impression sont revenues aux paramètres par défaut:

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

Pour éviter des zéros d'être dépouillé de la fin des flotteurs:

np.set_printoptions a maintenant un paramètre formatter qui vous permet de spécifier une fonction de format pour chaque type.

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

qui imprime

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

au lieu de

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

est là un moyen t o appliquer la mise en forme uniquement à l'instruction print spécifique (par opposition à la définition d'un format de sortie général utilisé par * all * print statements)? – bph

+5

@Hiett: Il n'y a pas de fonction NumPy pour définir les options d'impression pour un seul 'print', mais vous pouvez utiliser un gestionnaire de contexte pour créer quelque chose de similaire. J'ai modifié le post ci-dessus pour montrer ce que je veux dire. – unutbu

+7

+1 pour le gestionnaire de contexte – fotNelton

29

Unutbu a donné une réponse très complète (ils ont obtenu un +1 de moi aussi), mais voici une alternative 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'] 

En fonction (En utilisant la syntaxe format() pour le formatage):

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

Utilisation:

>>> 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 du tableau est accessible dans la chaîne de format:

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

Des années plus tard, un autre est au dessous de. Mais pour un usage quotidien que je viens

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

Et voici ce que je l'utilise, et il est assez simple:

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

numpy.char.mod peut également être utile, selon les détails de votre application par exemple: numpy.char.mod('Value=%4.2f', numpy.arange(5, 10, 0.1)) retournera un tableau de chaînes avec les éléments "Valeur = 5.00", "Valeur = 5.10" etc. (comme un exemple un peu artificiel).

25

Vous pouvez obtenir un sous-ensemble de la fonctionnalité np.set_printoptions à partir de la commande np.array_str, qui s'applique uniquement à une seule instruction d'impression.

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

Par exemple:

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

Je veux souvent différentes colonnes d'avoir des formats différents. Voici comment imprimer simple tableau 2D en utilisant une variété dans la mise en forme en convertissant (tranches de) Mon tableau NumPy à un tuple:

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

Le joyau qui le rend trop facile d'obtenir le résultat en tant que chaîne (dans les versions numpy d'aujourd'hui) est caché dans la réponse 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]' 
0

une autre option est d'utiliser le module 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'] 
Questions connexes