问题描述
我最近注意到NumPy ndarays的Python打印功能不一致.例如,它水平打印水平的一维数组:
I have recently noticed that Python printing functionality is not consistent for NumPy ndarays. For example it prints a horizontal 1D array horizontally:
import numpy as np
A1=np.array([1,2,3])
print(A1)
#--> [1 2 3]
但是一维水平数组,且垂直有多余的括号:
but a 1D horizontal array with redundant brackets vertically:
A2=np.array([[1],[2],[3]])
print(A2)
#--> [[1]
# [2]
# [3]]
水平的一维垂直阵列:
A3=np.array([[1,2,3]])
print(A3)
#--> [[1 2 3]]
和2D数组:
B=np.array([[11,12,13],[21,22,23],[31,32,32]])
print(B)
# --> [[11 12 13]
# [21 22 23]
# [31 32 32]]
第一个尺寸现在是垂直的.对于更高尺寸的尺寸,情况更糟,因为它们都是垂直打印的:
where the first dimension is now vertical. It gets even worse for higher dimensions as all of them are printed vertically:
C=np.array([[[111,112],[121,122]],[[211,212],[221,222]]])
print(C)
#--> [[[111 112]
# [121 122]]
#
# [[211 212]
# [221 222]]]
我认为,一致的行为是水平打印偶数尺寸,垂直打印奇数尺寸.使用Unicode字符,可以很好地格式化它.我想知道是否可以创建一个函数来打印上面的数组:
A consistent behavior in my opinion would be to print the even dimensions horizontally and odd ones vertically. Using Unicode characters it would be possible to format it nicely. I was wondering if it is possible to create a function to print above arrays as:
A1 --> [1 2 3]
A2 --> ┌┌─┐┌─┐┌─┐┐
│ 1 2 3 │
└└─┘└─┘└─┘┘
A3 --> ┌┌─┐┐ # \u250c\u2500\u2510
│ 1 │ # \u2502
│ 2 │
│ 3 │
└└─┘┘ # \u2514\u2500\u2518
B --> ┌┌──┐┌──┐┌──┐┐
│ 11 21 31 │
│ 12 22 32 │
│ 13 23 33 │
└└──┘└──┘└──┘┘
C --> ┌┌─────────┐┌─────────┐┐
│ [111 112] [211 212] │
│ [121 122] [221 222] │
└└─────────┘└─────────┘┘
我发现这个要点可以处理不同位数的数字.我试图为递归函数创建原型以实现上述概念:
I found this gist which takes care of the different number of digits. I tried to prototype a recursive function to implement the above concept:
def npprint(A):
assert isinstance(A, np.ndarray), "input of npprint must be array like"
if A.ndim==1 :
print(A)
else:
for i in range(A.shape[1]):
npprint(A[:,i])
这有点适用于A1
,A2
,A3
和B
,但不适用于C
.如果您能帮助我知道npprint
应该如何实现任意维数numpy ndarrays的上述输出,我将不胜感激.
It kinda works for A1
, A2
, A3
and B
but not for C
. I would appreciate if you could help me know how the npprint
should be to achieve above output for arbitrary dimension numpy ndarrays?
P.S.1..在Jupyter环境中,可以在Markdown中使用LaTeX \mathtools
\underbracket
和\overbracket
. Sympy的漂亮打印功能也是一个很好的起点.它可以使用ASCII,Unicode,LaTeX ...
P.S.1. In Jupyter environment one can use LaTeX \mathtools
\underbracket
and \overbracket
in Markdown. Sympy's pretty printing functionality is also a great start point. It can use ASCII, Unicode, LaTeX...
P.S.2..有人告诉我,ndarray的打印方式确实存在一致性.但是恕我直言,这是一种有线的和非直觉的.具有灵活漂亮的打印功能可以帮助以各种形式显示ndarray.
P.S.2. I'm being told that there is indeed a consistency in the way ndarrays are being printed. however IMHO it is kind of wired and non-intuitive. Having a flexible pretty printing function could help a lot to display ndarrays in different forms.
P.S.3..Sympy家伙已经考虑了我在这里提到的两点.它们的Matrix模块非常一致(A1
和A2
是相同的),并且它们还具有pprint
函数,该函数执行相同的操作,我希望在这里npprint.
P.S.3. Sympy guys have already considered both points I have mentioned here. their Matrix module is pretty consistent (A1
and A2
are the same) and they also have a pprint
function which does kind of the same thing and I expect from npprint here.
PS4.对于那些遵循此想法的人,我将所有内容都集成在此Jupyter笔记本
P.S.4. For those who follow up this idea I have integrated everythin here in this Jupyter Notebook
推荐答案
对我而言,了解numpy数组与我想到的MATLAB矩阵或多维数学数组完全不同,这对我来说是一个很大的启示.它们是同质且统一的嵌套Python列表.我还了解到,numpy数组的第一维是水平括号内最深/最里面的方括号,水平打印,然后从此处垂直打印第二维,第三维以空格隔开...
It was quite a revelation to me understanding numpy arrays are not anything like MATLAB matrices or multidimensional mathematical arrays I had in mind. They are rather homogeneous and uniform nested Python lists. I also understood that the first dimension of a numpy array is the most deepest/inner pairs of square brackets which is printed horizontally and then from there second dimension is printed vertically, Third vertically with a spaced line...
无论如何,具有ppring
函数(受Sympy的命名约定启发)对我有很大帮助.因此,我将在此处提出一个非常糟糕的实现,希望它能启发其他高级Pythoner提出更好的解决方案:
Anyways I thing having an ppring
function (inspired by Sympy's naming convention) could help a lot. so I'm going to put a very bad implementation here hoping it will inspire other advanced Pythoners to come up with better solutions:
def pprint(A):
if A.ndim==1:
print(A)
else:
w = max([len(str(s)) for s in A])
print(u'\u250c'+u'\u2500'*w+u'\u2510')
for AA in A:
print(' ', end='')
print('[', end='')
for i,AAA in enumerate(AA[:-1]):
w1=max([len(str(s)) for s in A[:,i]])
print(str(AAA)+' '*(w1-len(str(AAA))+1),end='')
w1=max([len(str(s)) for s in A[:,-1]])
print(str(AA[-1])+' '*(w1-len(str(AA[-1]))),end='')
print(']')
print(u'\u2514'+u'\u2500'*w+u'\u2518')
结果对于1D和2D数组是可以接受的:
and the result is somewhat acceptable for 1D and 2D arrays:
B1=np.array([[111,122,133],[21,22,23],[31,32,33]])
pprint(B1)
#┌─────────────┐
# [111 122 133]
# [21 22 23 ]
# [31 32 33 ]
#└─────────────┘
这确实是一个非常糟糕的代码,它仅适用于整数.希望其他人会提出更好的解决方案.
this is indeed a very bad code, it only works for integers. hopefully others will come up with better solutions.
PS1. Eric Wieser 已经实现了一个非常漂亮的HTML原型可在此处看到的IPython/Jupiter :
P.S.1. Eric Wieser has already implemented a very nice HTML prototype for IPython/Jupiter which can seen here:
您可以关注有关numpy邮件列表的讨论此处.
You may follow the discussion on numpy mailing list here.
PS2.我还发布了这个想法在Reddit上.
P.S.2. I also posted this idea here on Reddit.
P.S.3 我花了一些时间将代码扩展到3D维度数组:
P.S.3 I spent some time to extend the code to 3D dimensional arrays:
def ndtotext(A, w=None, h=None):
if A.ndim==1:
if w == None :
return str(A)
else:
s= '['
for i,AA in enumerate(A[:-1]):
s += str(AA)+' '*(max(w[i],len(str(AA)))-len(str(AA))+1)
s += str(A[-1])+' '*(max(w[-1],len(str(A[-1])))-len(str(A[-1]))) +'] '
elif A.ndim==2:
w1 = [max([len(str(s)) for s in A[:,i]]) for i in range(A.shape[1])]
w0 = sum(w1)+len(w1)+1
s= u'\u250c'+u'\u2500'*w0+u'\u2510' +'\n'
for AA in A:
s += ' ' + ndtotext(AA, w=w1) +'\n'
s += u'\u2514'+u'\u2500'*w0+u'\u2518'
elif A.ndim==3:
h=A.shape[1]
s1=u'\u250c' +'\n' + (u'\u2502'+'\n')*h + u'\u2514'+'\n'
s2=u'\u2510' +'\n' + (u'\u2502'+'\n')*h + u'\u2518'+'\n'
strings=[ndtotext(a)+'\n' for a in A]
strings.append(s2)
strings.insert(0,s1)
s='\n'.join(''.join(pair) for pair in zip(*map(str.splitlines, strings)))
return s
,例如:
shape = 4, 3, 6
B2=np.arange(np.prod(shape)).reshape(shape)
print(B2)
print(ndtotext(B2))
[[[ 0 1 2 3 4 5]
[ 6 7 8 9 10 11]
[12 13 14 15 16 17]]
[[18 19 20 21 22 23]
[24 25 26 27 28 29]
[30 31 32 33 34 35]]
[[36 37 38 39 40 41]
[42 43 44 45 46 47]
[48 49 50 51 52 53]]
[[54 55 56 57 58 59]
[60 61 62 63 64 65]
[66 67 68 69 70 71]]]
┌┌───────────────────┐┌───────────────────┐┌───────────────────┐┌───────────────────┐┐
│ [0 1 2 3 4 5 ] [18 19 20 21 22 23] [36 37 38 39 40 41] [54 55 56 57 58 59] │
│ [6 7 8 9 10 11] [24 25 26 27 28 29] [42 43 44 45 46 47] [60 61 62 63 64 65] │
│ [12 13 14 15 16 17] [30 31 32 33 34 35] [48 49 50 51 52 53] [66 67 68 69 70 71] │
└└───────────────────┘└───────────────────┘└───────────────────┘└───────────────────┘┘
这篇关于使用unicode字符漂亮地打印numpy ndarrays的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!