0

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
4
  • im not sure i understand what you mean by row representation, did you mean you want to Print them to console next to each other? Commented Mar 22, 2016 at 2:47
  • In one row, just like the image, as text, there are 3 rows (ie, 3 rows of 2D array blocks). For some people, representation is better understood if the contents are laid out on one row, rather than 3. Use the graph as your guide, it was constructed from the data by using a (1,3) subplot. Unfortunately, there isn't an equivalent for arrays. Even if you use a (1,3) array with dtype='object' it gets me no further to getting a text structure that I can use. As indicated, this is for visualization, not analysis and a 3D array is as far as it is going to go. Commented Mar 22, 2016 at 2:59
  • if you want to print them side by side, you're stuck printing m0row0 m1row0 m2row0/nm0row1 m1row1 m2row2/netc Commented Mar 22, 2016 at 3:23
  • that is the kludge I am using, I have added it to the question. I just want to make sure that there is no way of flattening, and restriding and/or slicing the input to get the result Commented Mar 22, 2016 at 4:04

1 Answer 1

1

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.

Sign up to request clarification or add additional context in comments.

3 Comments

that formatting by plane may be the way to go for me initially, since my conditions are limited to a few cases, this will work nicely. I just wanted to ensure that I wasn't missing something fundamental.
Most arrays have more than 3 columns, so displaying planes side by side isn't useful. In fact you can see from printoptions that the developers worried more about arrays that were too big to display conveniently (without ellipsis).
Yes, something like x = np.arange(3*25*3).reshape((3,25,3)) would produce too many lines unless np.set_printoptions(edgeitems=2,linewidth=80,threshold=10) was used (integer case). My intent is to compliment the vertical orientation in a horizontal fashion, as in my figure. Some students understand the horizontally orientation. They are transitioning from thinking in terms of rows, columns and layers/sheets/tables. If any of the dimensions is too large, then seeing it in text form without ellipses is pretty useless. I move on to mapping in the GIS sense of the term after this.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.