最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

python - Printing numpy matrices horizontally on the console - Stack Overflow

programmeradmin0浏览0评论

Numpy has many nice features for formatted output, but something I miss is the ability to print more than one array/matrix on the same line. What I mean is easiest to explain with an example. Given the following code:

A = np.random.randint(10, size = (4, 4))
B = np.random.randint(10, size = (4, 4))
niceprint(A, "*", B, "=", A @ B)

How can you implement niceprint so that it prints the following on the console?

[[7 1 0 4]      [[8 6 2 6]     [[ 80  45  54  83]
 [8 1 5 8]   *   [0 3 8 5]  =   [147  91 123 140]
 [3 7 2 4]       [7 8 7 3]      [ 62  55 108  95]
 [8 8 2 8]]      [6 0 8 9]]     [126  88 158 166]]

Numpy has many nice features for formatted output, but something I miss is the ability to print more than one array/matrix on the same line. What I mean is easiest to explain with an example. Given the following code:

A = np.random.randint(10, size = (4, 4))
B = np.random.randint(10, size = (4, 4))
niceprint(A, "*", B, "=", A @ B)

How can you implement niceprint so that it prints the following on the console?

[[7 1 0 4]      [[8 6 2 6]     [[ 80  45  54  83]
 [8 1 5 8]   *   [0 3 8 5]  =   [147  91 123 140]
 [3 7 2 4]       [7 8 7 3]      [ 62  55 108  95]
 [8 8 2 8]]      [6 0 8 9]]     [126  88 158 166]]
Share Improve this question asked Mar 28 at 10:44 Gaslight Deceive SubvertGaslight Deceive Subvert 20.5k20 gold badges91 silver badges129 bronze badges 2
  • 1 there was similar question about two tables - python - How to place tables next to each other with tabulate - Stack Overflow - solution can be similar: first create strings with arrays and later use zip() to group first lines from all arrays, second lines, third lines, etc. and display all first lines as one string, next all second lines as one string, etc. – furas Commented Mar 28 at 14:35
  • Have you considered Sympy? Even if you don't need it for any actual "calculation", it has a lot of pretty-print code including for matrices. – Reinderien Commented Mar 30 at 13:26
Add a comment  | 

2 Answers 2

Reset to default 1

It may need similar method like in answer for
python - How to place tables next to each other with tabulate - Stack Overflow

it needs to convert all arrays to strings and split them to lists of lines, and next it needs zip() or better zip_longest(..., fillvalue="") to group first line (and print them as one string, second lines (and print them as string, with * and =), etc.

Because last line has longer (because it has closing ] at the end) so I use f-string with {variable:length} to set extra space in previous lines.

It also adds empty lines below array A to put array B in correct place

Because arrays may have different number of lines so it is good to use zip_longest() instead of zip() and use fillvalue='' to put missing lines.

To show this problem I use 4x6 and 6x4 instead of 4x4

import numpy as np
from itertools import zip_longest

A = np.random.randint(10, size = (4, 6))
B = np.random.randint(10, size = (6, 4))
C = A@B

a = str(A).split('\n')
b = str(B).split('\n')
c = str(C).split('\n')

a_len = len(a[0]) + 1
b_len = len(b[0]) + 1
#c_len = len(c[0]) + 1

for index, (x, y, z) in enumerate(zip_longest(a, b, c, fillvalue='')):
    if index == 1:
        print(f'{x:{a_len}} * {y:{b_len}} = {z}')
    else:
        print(f'{x:{a_len}}   {y:{b_len}}   {z}')

Result:

[[4 3 0 5 1 6]    [[8 3 5 8]    [[ 89 137 104  94]
 [6 3 5 7 3 0]  *  [5 9 8 6]  =  [128 148 104 149]
 [6 6 6 1 7 6]     [9 5 6 5]     [178 194 178 148]
 [9 8 0 3 2 8]]    [2 9 2 7]     [162 200 183 155]]
                   [2 5 2 3]    
                   [5 8 8 1]] 

EDIT:

If you want to center operator then you need height and calculate center and use it with index

height = max(len(a), len(b), len(c))
center = round(height/2)-1   # `round(height/2)` gives better output than `height//2`

# ... code

    if index == center:
        print(f'{x:<{a_len}} * {y:{b_len}} = {z}')

# ... code

Result:

[[4 8 0 0 5 2]    [[5 9 9 4]    [[128  96  87 122]
 [9 4 0 6 8 3]     [9 3 2 7]     [161 191 180 155]
 [4 9 7 8 9 3]  *  [0 7 8 9]  =  [193 228 218 245]
 [7 6 6 6 8 1]]    [4 7 6 2]     [153 205 204 205]]
                   [4 4 5 8]    
                   [8 8 5 5]] 

BTW: You could try to use height-len(a), etc. add empty rows before array - to center also arrays.


Because it works with strings so it doesn't matter if you have integer of float values

# float values
A = np.random.randint(10, size = (4, 6)) / 10
B = np.random.randint(10, size = (6, 4)) / 10

Result:

[[0.3 0.3 0.3 0.9 0.2 0.6]    [[0.5 0.3 0.2 0.5]    [[0.3  0.9  0.65 1.31]
 [0.2 0.7 0.2 0.5 0.4 0.8]     [0.1 0.6 0.6 0.9]     [0.33 1.3  1.   1.79]
 [0.3 0.  0.1 0.  0.9 0.9]  *  [0.  0.7 0.1 0.9]  =  [0.33 1.33 0.7  1.41]
 [0.4 0.  0.4 0.6 0.4 0.5]]    [0.  0.  0.  0. ]     [0.3  0.96 0.46 1.17]]
                               [0.  0.9 0.1 0.4]    
                               [0.2 0.4 0.6 0.9]] 

I don't have example with n-dimention array but it should also work.

It may need to get lenght of last element in list (and without +1)

a_len = len(a[-1])
b_len = len(b[-1])

Full working code used for tests with different shapes, integer or float values and with N-dimension

import numpy as np
from itertools import zip_longest

def niceprint(A, op, B, C):
    a = str(A).split('\n')
    b = str(B).split('\n')
    c = str(C).split('\n')

    a_len = len(a[-1])
    b_len = len(b[-1])

    height = max(len(a), len(b), len(c))
    center = round(height/2)-1   # `round(height/2)` gives better position than `height//2`

    for index, (x, y, z) in enumerate(zip_longest(a, b, c, fillvalue='')):
        if index == center:
            print(f'{x:<{a_len}} {op} {y:{b_len}} = {z}')
        else:
            print(f'{x:<{a_len}}   {y:{b_len}}   {z}')

# ---

def example1():
    A = np.random.randint(10, size = (4, 6))
    B = np.random.randint(10, size = (6, 4))
    C = A@B
    niceprint(A, '*', B, C)

def example2():
    A = np.random.randint(10, size = (3, 3, 3)) / 10
    B = np.random.randint(10, size = (3, 3, 3)) / 10
    C = A+B
    niceprint(A, '+', B, C)

def example3():
    A = np.random.randint(10, size = (2, 3, 3, 2)) / 10
    B = np.random.randint(10, size = (2, 3, 3, 2)) / 10
    C = A+B
    niceprint(A, '+', B, C)

#example1()
#example2()
example3()

Don't write it yourself; use something common and off-the-shelf like Sympy.

import numpy as np
import sympy

A = sympy.Matrix(np.random.randint(10, size=(4, 4)))
B = sympy.Matrix(np.random.randint(10, size=(4, 4)))

sympy.pretty_print(
    sympy.Eq(
        sympy.MatMul(A, B),
        A @ B,
    )
)
⎡4  2  1  5⎤ ⎡3  0  7  7⎤   ⎡77   54   42  58 ⎤
⎢          ⎥ ⎢          ⎥   ⎢                 ⎥
⎢1  6  5  1⎥ ⎢9  5  0  1⎥   ⎢76   82   29  57 ⎥
⎢          ⎥⋅⎢          ⎥ = ⎢                 ⎥
⎢3  3  7  0⎥ ⎢2  9  4  8⎥   ⎢50   78   49  80 ⎥
⎢          ⎥ ⎢          ⎥   ⎢                 ⎥
⎣7  6  2  8⎦ ⎣9  7  2  4⎦   ⎣151  104  73  103⎦
发布评论

评论列表(0)

  1. 暂无评论