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

后端 未结 14 2171
臣服心动
臣服心动 2020-11-22 04:28

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


        
相关标签:
14条回答
  • 2020-11-22 04:29

    I find that the usual float format {:9.5f} works properly -- suppressing small-value e-notations -- when displaying a list or an array using a loop. But that format sometimes fails to suppress its e-notation when a formatter has several items in a single print statement. For example:

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

    My results show the bug in cases 4, 5, and 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
    

    I have no explanation for this, and therefore I always use a loop for floating output of multiple values.

    0 讨论(0)
  • 2020-11-22 04:29

    numpy.char.mod may also be useful, depending on the details of your application e.g.:numpy.char.mod('Value=%4.2f', numpy.arange(5, 10, 0.1)) will return a string array with elements "Value=5.00", "Value=5.10" etc. (as a somewhat contrived example).

    0 讨论(0)
  • 2020-11-22 04:31

    Was surprised to not see around method mentioned - means no messing with print options.

    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]]
    
    0 讨论(0)
  • 2020-11-22 04:33

    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']
    
    0 讨论(0)
  • 2020-11-22 04:33

    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
    
    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
    
    0 讨论(0)
  • 2020-11-22 04:34

    The numpy arrays have the method round(precision) which return a new numpy array with elements rounded accordingly.

    import numpy as np
    
    x = np.random.random([5,5])
    print(x.round(3))
    
    0 讨论(0)
提交回复
热议问题