如何在没有科学记数法和给定精度的情况下漂亮地打印 numpy.array?
Posted
技术标签:
【中文标题】如何在没有科学记数法和给定精度的情况下漂亮地打印 numpy.array?【英文标题】:How to pretty-print a numpy.array without scientific notation and with given precision? 【发布时间】:2011-02-22 22:08:57 【问题描述】:我很好奇,是否有任何方法可以打印格式化的numpy.arrays
,例如,以类似于以下的方式:
x = 1.23456
print '%.3f' % x
如果我想打印浮点数的numpy.array
,它会打印几个小数,通常是“科学”格式,即使是低维数组也很难阅读。但是,numpy.array
显然必须打印为字符串,即使用%s
。有解决方案吗?
【问题讨论】:
this discussion 也可能对那些通过谷歌搜索结束的人感兴趣。 【参考方案1】:你可以使用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. ]
请参阅docs for set_printoptions 了解其他选项。
要在本地应用打印选项,使用 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]
【讨论】:
有没有办法只将格式应用于特定的打印语句(而不是设置 all 打印语句使用的一般输出格式)? @Hiett:没有 NumPy 函数可以仅为一个print
设置打印选项,但您可以使用上下文管理器来进行类似的操作。我已经编辑了上面的帖子以说明我的意思。
你的np.set_printoptions(precision=3)
抑制结束零.. 你如何让它们像这样显示[ 0.078 0.480 0.413 0.830 0.776 0.102 0.513 0.462 0.335 0.712]
?
@Norfeldt:我在上面添加了一种方法。
这很好用。附带说明一下,如果您想要字符串表示,也可以使用set_printoptions
,而不必使用print
。您只需调用 numpy 数组实例的__str__()
,您将根据您设置的打印选项获得格式化字符串。【参考方案2】:
您可以从np.array_str
命令获取np.set_printoptions
功能的子集,该功能仅适用于单个打印语句。
http://docs.scipy.org/doc/numpy/reference/generated/numpy.array_str.html
例如:
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. ]]
【讨论】:
可能是最简单有效的选项,因为它不会在printoptions
中引入永久性更改,也不需要昂贵的循环或 with
构造。格式化元素的可能性应该直接集成到numpy中(不明白为什么不是这样)。【参考方案3】:
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']
【讨论】:
【参考方案4】:仅供参考 Numpy 1.15(发布日期待定)将include a context manager for setting print options locally。这意味着以下内容将与the accepted answer(由 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]
【讨论】:
【参考方案5】:使获取结果作为字符串变得非常容易(在今天的 numpy 版本中)的 gem 隐藏在 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]'
【讨论】:
【参考方案6】:多年后,下面是另一个。但对于日常使用,我只是
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://***.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
【讨论】:
【参考方案7】:这是我使用的,非常简单:
print(np.vectorize("%.2f".__mod__)(sparse))
【讨论】:
【参考方案8】:很惊讶没有看到提到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]]
【讨论】:
但这确实意味着每次要打印数组时都要创建第二个副本,这可能会阻止某些用例。【参考方案9】:numpy 数组有 round(precision)
方法,它返回一个新的 numpy 数组,其中元素相应地四舍五入。
import numpy as np
x = np.random.random([5,5])
print(x.round(3))
【讨论】:
在将数组传递给 matplotlib ylabel 时,这对我有用,谢谢【参考方案10】:我经常希望不同的列具有不同的格式。以下是我如何通过将我的 NumPy 数组(切片)转换为元组来使用多种格式打印一个简单的二维数组:
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,:]))
【讨论】:
【参考方案11】:我发现在使用循环显示列表或数组时,通常的浮点格式 :9.5f 可以正常工作——抑制小值电子符号。但是当格式化程序在单个打印语句中有多个项目时,该格式有时无法抑制其电子符号。例如:
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
我对此没有任何解释,因此我总是使用循环来实现多个值的浮动输出。
【讨论】:
【参考方案12】:我用
def np_print(array,fmt="10.5f"):
print (array.size*(":"+fmt+"")).format(*array)
多维数组修改并不难。
【讨论】:
【参考方案13】:numpy.char.mod
也可能有用,具体取决于您的应用程序的详细信息,例如:numpy.char.mod('Value=%4.2f', numpy.arange(5, 10, 0.1))
将返回一个字符串数组,其中包含元素“Value=5.00”、“Value=5.10”等(作为一个有点人为的例子) .
【讨论】:
【参考方案14】:另一个选择是使用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']
【讨论】:
以上是关于如何在没有科学记数法和给定精度的情况下漂亮地打印 numpy.array?的主要内容,如果未能解决你的问题,请参考以下文章