本文介绍了使用unicode字符漂亮地打印numpy ndarrays的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我最近注意到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])

这有点适用于A1A2A3B,但不适用于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模块非常一致(A1A2是相同的),并且它们还具有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的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-18 09:39