Display Multidimensional Arrays
I was testing nimib while trying to reproduce arraymancer tutorial, and I ran into some issues that arraymancer currently has when displaying tensors. This got me to ask myself:
How do I display a multidimensional array with 3 or 4 (or more) dimensions?
Other languages
Let us look into how other languages (Python, R) do it. I also get the opportunity of trying out the existing bridges.
import
sequtils, nimpy, rnim
Python
Using nimpy
let np = pyImport("numpy")
var a = np.arange(15)
echo a
[ 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14]
sometimes you see the repr
of the array:
let py = pyBuiltinsModule()
echo py.repr(a)
array([ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14])
let's go in two dimensions:
a = a.reshape(3, 5)
echo a
[[ 0 1 2 3 4] [ 5 6 7 8 9] [10 11 12 13 14]]
now three:
a = np.arange(12).reshape(2, 2, 3)
echo a
[[[ 0 1 2] [ 3 4 5]] [[ 6 7 8] [ 9 10 11]]]
and four:
a = np.arange(16).reshape(2, 2, 2, 2)
echo a
[[[[ 0 1] [ 2 3]] [[ 4 5] [ 6 7]]] [[[ 8 9] [10 11]] [[12 13] [14 15]]]]
and in fact numpy has a very simple layout when printing arrays
- the last axis is printed from left to right,
- the second-to-last is printed from top to bottom,
- the rest are also printed from top to bottom, with each slice separated from the next by an empty line.
and this carries on with 5 or more dimensions:
a = np.arange(32).reshape(2, 2, 2, 2, 2)
echo a
[[[[[ 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]]]]]
Note that lists of matrices have one empty line between matrices, lists of lists of matrices have two empty lines between lists of matrices and lists of lists of lists of matrices have three empty lines between lists of lists of lists of matrices.
R
Using rnim.
First example in R would be: array(1:15)
.
let R = setupR()
var a = R.array(toSeq(1 .. 15))
echo R.print(a)
## echo a # only prints the type info without content
## discard R.print(a) # prints nothing
echo R.str(a)
[1] 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 Type: REALSXP attrib: LIST: car = Type: INTSXP , cdr = nil, internal = Type: SYMSXP num [1:15(1d)] 1 2 3 4 5 6 7 8 9 10 ... nil
I do not know how to obtain a decent display, in R only the line before Type is shown.
Two dimensions (R equivalent: array(1:15, c(3, 5))
):
a = R.array(toSeq(1 .. 15), @[3, 5])
echo R.print(a)
[,1] [,2] [,3] [,4] [,5] [1,] 1 4 7 10 13 [2,] 2 5 8 11 14 [3,] 3 6 9 12 15 Type: REALSXP attrib: LIST: car = Type: INTSXP , cdr = nil, internal = Type: SYMSXP
now three:
a = R.array(toSeq(1 .. 12), @[2, 2, 3])
echo R.print(a)
, , 1 [,1] [,2] [1,] 1 3 [2,] 2 4 , , 2 [,1] [,2] [1,] 5 7 [2,] 6 8 , , 3 [,1] [,2] [1,] 9 11 [2,] 10 12 Type: REALSXP attrib: LIST: car = Type: INTSXP , cdr = nil, internal = Type: SYMSXP
and four:
a = R.array(toSeq(1 .. 16), @[2, 2, 2, 2])
echo R.print(a)
, , 1, 1 [,1] [,2] [1,] 1 3 [2,] 2 4 , , 2, 1 [,1] [,2] [1,] 5 7 [2,] 6 8 , , 1, 2 [,1] [,2] [1,] 9 11 [2,] 10 12 , , 2, 2 [,1] [,2] [1,] 13 15 [2,] 14 16 Type: REALSXP attrib: LIST: car = Type: INTSXP , cdr = nil, internal = Type: SYMSXP