在没有科学记数法且给定精度的情况下漂亮地打印 NumPy 数组

问题描述 投票:0回答:14

如何以类似于此的方式打印格式化的 NumPy 数组:

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

如果我想打印浮点数的

numpy.ndarray
,它会打印几个小数,通常以“科学”格式,即使对于低维数组也很难读取。然而,显然必须将
numpy.ndarray
打印为字符串,即使用
%s
。有解决办法吗?

python numpy pretty-print
14个回答
751
投票

使用

numpy.set_printoptions
设置输出的精度:

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]

并且

suppress
禁止对小数使用科学记数法:

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

要在本地应用打印选项,使用 NumPy 1.15.0 或更高版本,您可以使用

numpy.printoptions
上下文管理器。 例如,在
with-suite
precision=3
suppress=True
里面设置:

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]

但在

with-suite
之外,打印选项将恢复为默认设置:

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

如果您使用的是早期版本的 NumPy,您可以创建上下文管理器 你自己。例如,

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]

为了防止零从浮点数末尾被剥离:

np.set_printoptions
现在有一个
formatter
参数,允许您为每种类型指定格式函数。

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

打印

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

73
投票

使用

np.array_str
仅将格式应用于单个打印语句。它提供了
np.set_printoptions
功能的子集。

例如:

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

46
投票

Unutbu 给出了一个非常完整的答案(他们也从我这里得到了 +1),但这里有一个低技术替代方案:

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

作为函数(使用

format()
语法进行格式化):

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

用途:

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

可以通过格式字符串访问数组的索引:

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

19
投票

仅供参考,Numpy 1.15(发布日期待定)将包括一个用于本地设置打印选项的上下文管理器。这意味着以下内容将与“接受的答案”(由 unutbu 和 Neil G 编写)中的相应示例相同,而无需编写自己的上下文管理器。例如,使用他们的例子: 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]



16
投票

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



11
投票

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


8
投票

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



8
投票

round

 方法,如 
x.round(precision) 中所示,它返回一个新的 numpy 数组,其中元素相应地舍入。
import numpy as np

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



6
投票
around

方法 - 意味着不会弄乱打印选项。


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



2
投票

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,:]))



2
投票

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

我的结果显示了案例 4、5 和 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

我对此没有任何解释,因此我总是使用循环来浮动输出多个值。 


2
投票

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

对于多维数组修改起来并不困难。


1
投票

numpy.char.mod

 也可能很有用,具体取决于您的应用程序的详细信息,例如:
numpy.char.mod('Value=%4.2f', numpy.arange(5, 10, 0.1)) 将返回一个包含元素“Value=5.00”、“Value=5.10”等的字符串数组(作为一个有点人为的示例) .
    


0
投票
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']

© www.soinside.com 2019 - 2024. All rights reserved.