user1121588
user1121588

Reputation:

numpy array representation and formatting

I am working with some documentation and wish to portray an array of this form

>>> a_3d
array([[[4, 6, 4],
        [1, 1, 8],
        [0, 7, 5],
        [5, 3, 3],
        [8, 9, 5]],

       [[8, 8, 4],
        [3, 4, 4],
        [0, 0, 9],
        [3, 7, 3],
        [3, 4, 7]],

       [[9, 5, 4],
        [7, 7, 3],
        [9, 5, 9],
        [8, 7, 8],
        [5, 8, 8]]], dtype=int32)

as text in a similar fashion as I can do it using MatPlotLib as a graph/map.

array viewed as row

I have managed to simply decompress the original array and provide some additional information into this form.

array...
shape (3, 5, 3) ndim 3 size 45
a[0]...
[[[4 6 4]
  [1 1 8]
  [0 7 5]
  [5 3 3]
  [8 9 5]]
a[1]....
 [[8 8 4]
  [3 4 4]
  [0 0 9]
  [3 7 3]
  [3 4 7]]
a[2]....
 [[9 5 4]
  [7 7 3]
  [9 5 9]
  [8 7 8]
  [5 8 8]]]

But I have tried every combination of reshaping, transposing to get it into a row representation. I haven't found a soution, short of reconstructing the array from first principles so that the three 2D blocks appear in one row.

Again, this is for teaching and visualization purposes and not for analysis. If I have overlooked the obvious, I would appreciate any comments.

EDIT

 [[[4, 6, 4],  [[8, 8, 4],   [[9, 5, 4],
   [1, 1, 8],     
   [0, 7, 5],     etc            etc
   [5, 3, 3],
   [8, 9, 5]],  [3, 4, 7]],   [5, 8, 8]]]

or similar... if this helps apparently the kludge workaround I am using might help, it would be nice to work with the original data and restructure it, rather than to have to say...we will flip out to using lists and object arrays for awhile...

def to_row(a):
    """ kludge workaround   """
    n, rows, cols = a.shape
    e = np.empty((rows, cols), dtype='object')
    for r in range(rows):
        for c in range(cols):
            e[r][c] = (a[c][r]).tolist()
    return e

Upvotes: 0

Views: 648

Answers (1)

hpaulj
hpaulj

Reputation: 231335

So you have an array with shape (3,5,3), and the default array function displays it has 3 planes, each a (5,3) 2d array.

Reshaping and transposing does not change this basic display format - it still splits the array on the 1st axis, and formats each block.

The formatting is handled by a builtin numpy function:

In [112]: arr=np.arange(2*3*4).reshape(2,3,4)

In [113]: arr.__format__('')
Out[113]: '[[[ 0  1  2  3]\n  [ 4  5  6  7]\n  [ 8  9 10 11]]\n\n [[12 13 14 15]\n  [16 17 18 19]\n  [20 21 22 23]]]'

np.array2string(arr) produces the same string.

Conceivably you could split this string on \n, and rearrange the pieces.

In [116]: np.get_printoptions()
Out[116]: 
{'edgeitems': 3,
 'formatter': None,
 'infstr': 'inf',
 'linewidth': 75,
 'nanstr': 'nan',
 'precision': 8,
 'suppress': False,
 'threshold': 1000}

the set_options function's doc describes these values. You might also look at np.set_string_function


Here's a first stab at rearranging the lines:

In [137]: astr=np.array2string(arr)
In [138]: lines=astr.splitlines()
In [139]: lines
Out[139]: 
['[[[ 0  1  2  3]',
 '  [ 4  5  6  7]',
 '  [ 8  9 10 11]]',
 '',
 ' [[12 13 14 15]',
 '  [16 17 18 19]',
 '  [20 21 22 23]]]']

In [140]: print '\n'.join(['   '.join((lines[i],lines[i+4])) for i in range(3)]) 
[[[ 0  1  2  3]    [[12 13 14 15]
  [ 4  5  6  7]     [16 17 18 19]
  [ 8  9 10 11]]     [20 21 22 23]]]

Brackets need to be cleaned up, but overall the shape looks right.

Another way to get such a set of lines is to format each plane:

In [151]: alist=[np.array2string(i).splitlines() for i in arr]

In [152]: alist
Out[152]: 
[['[[ 0  1  2  3]', ' [ 4  5  6  7]', ' [ 8  9 10 11]]'],
 ['[[12 13 14 15]', ' [16 17 18 19]', ' [20 21 22 23]]']]

In [153]: zip(*alist)   # a list form of transpose
Out[153]: 
[('[[ 0  1  2  3]', '[[12 13 14 15]'),
 (' [ 4  5  6  7]', ' [16 17 18 19]'),
 (' [ 8  9 10 11]]', ' [20 21 22 23]]')]

which then can be joined. \t (tab) cleans up the bracket spacing.

In [155]: '\n'.join(['\t'.join(k) for k in zip(*alist)])
Out[155]: '[[ 0  1  2  3]\t[[12 13 14 15]\n [ 4  5  6  7]\t [16 17 18 19]\n [ 8  9 10 11]]\t [20 21 22 23]]'

In [156]: print _
[[ 0  1  2  3]  [[12 13 14 15]
 [ 4  5  6  7]   [16 17 18 19]
 [ 8  9 10 11]]  [20 21 22 23]]

for 3 blocks - it still needs work :(

In [157]: arr1=np.arange(2*3*4).reshape(3,4,2)
In [158]: alist=[np.array2string(i).splitlines() for i in arr1]
In [159]: print '\n'.join(['\t'.join(k) for k in zip(*alist)])
[[0 1]  [[ 8  9]    [[16 17]
 [2 3]   [10 11]     [18 19]
 [4 5]   [12 13]     [20 21]
 [6 7]]  [14 15]]    [22 23]]

In a sense it's the same problem you have with text when you want to display it in columns. May be there's a multi-column print utility. Even though you are thinking in terms of blocks side by side, the display is still based on lines.

Upvotes: 1

Related Questions