# How to pretty-print a numpy.array without scientific notation and with given precision?

Posted on

Solving problem is about exposing yourself to as many situations as possible like How to pretty-print a numpy.array without scientific notation and with given precision? and practice these strategies over and over. With time, it becomes second nature and a natural way you approach any problems in general. Big or small, always start with a plan, use other strategies mentioned here till you are confident and ready to code the solution.
In this post, my aim is to share an overview the topic about How to pretty-print a numpy.array without scientific notation and with given precision?, which can be followed any time. Take easy to follow this discuss.

How to pretty-print a numpy.array without scientific notation and with given precision?

I’m curious, whether there is any way to print formatted `numpy.arrays`, e.g., in a way similar to this:

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

If I want to print the `numpy.array` of floats, it prints several decimals, often in ‘scientific’ format, which is rather hard to read even for low-dimensional arrays. However, `numpy.array` apparently has to be printed as a string, i.e., with `%s`. Is there a solution for this?

You can use `set_printoptions` to set the precision of the 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]
``````

And `suppress` suppresses the use of scientific notation for small numbers:

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

See the docs for set_printoptions for other options.

To apply print options locally, using NumPy 1.15.0 or later, you could use the numpy.printoptions context manager.
For example, inside the `with-suite` `precision=3` and `suppress=True` are set:

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

But outside the `with-suite` the print options are back to default settings:

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

If you are using an earlier version of NumPy, you can create the context manager
yourself. For example,

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

To prevent zeros from being stripped from the end of floats:

`np.set_printoptions` now has a `formatter` parameter which allows you to specify a format function for each type.

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

which prints

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

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

You can get a subset of the `np.set_printoptions` functionality from the `np.array_str` command, which applies only to a single print statement.

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

For example:

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

Unutbu gave a really complete answer (they got a +1 from me too), but here is a lo-tech alternative:

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

As a function (using the `format()` syntax for formatting):

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

Usage:

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

The index of the array is accessible in the format string:

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

FYI Numpy 1.15 (release date pending) will include a context manager for setting print options locally. This means that the following will work the same as the corresponding example in the accepted answer (by unutbu and Neil G) without having to write your own context manager. E.g., using their example:

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

The gem that makes it all too easy to obtain the result as a string (in today’s numpy versions) is hidden in denis answer:
`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]'
``````

Years later, another one is below. But for everyday use I just

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

And here is what I use, and it’s pretty uncomplicated:

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

Was surprised to not see `around` method mentioned – means no messing with print options.
``````import numpy as np