Mathews24 - 2 months ago 6x
Python Question

# Converting dictionary with known indices to a multidimensional array

I have a dictionary with entries labelled as

`{(k,i): value, ...}`
. I now want to convert this dictionary into a 2d array where the value given for an element of the array at position
`[k,i]`
is the value from the dictionary with label
`(k,i)`
. The length of the rows will not necessarily be of the same size (e.g. row
`k = 4`
may go up to index
`i = 60`
while row
`k = 24`
may go up to index
`i = 31`
). Due to the asymmetry, it is fine to make all additional entries in a particular row equal to 0 in order to have a rectangular matrix.

Here's an approach -

``````# Get keys (as indices for output) and values as arrays
idx = np.array(d.keys())
vals = np.array(d.values())

# Get dimensions of output array based on max extents of indices
dims = idx.max(0)+1

# Setup output array and assign values into it indexed by those indices
out = np.zeros(dims,dtype=vals.dtype)
out[idx[:,0],idx[:,1]] = vals
``````

We could also use sparse matrices to get the final output. e.g. with `coordinate format sparse matrices`. This would be memory efficient when kept as sparse matrices. So, the last step could be replaced by something like this -

``````from scipy.sparse import coo_matrix

out = coo_matrix((vals, (idx[:,0], idx[:,1])), dims).toarray()
``````

Sample run -

``````In [70]: d
Out[70]: {(1, 4): 120, (2, 2): 72, (2, 3): 100, (5, 2): 88}

In [71]: out
Out[71]:
array([[  0,   0,   0,   0,   0],
[  0,   0,   0,   0, 120],
[  0,   0,  72, 100,   0],
[  0,   0,   0,   0,   0],
[  0,   0,   0,   0,   0],
[  0,   0,  88,   0,   0]])
``````

To make it generic for ndarrays of any number of dimensions, we can use linear-indexing and use `np.put` to assign values into the output array. Thus, in our first approach, just replace the last step of assigning values with something like this -

``````np.put(out,np.ravel_multi_index(idx.T,dims),vals)
``````

Sample run -

``````In [106]: d
Out[106]: {(1,0,0): 99, (1,0,4): 120, (2,0,2): 72, (2,1,3): 100, (3,0,2): 88}

In [107]: out
Out[107]:
array([[[  0,   0,   0,   0,   0],
[  0,   0,   0,   0,   0]],

[[ 99,   0,   0,   0, 120],
[  0,   0,   0,   0,   0]],

[[  0,   0,  72,   0,   0],
[  0,   0,   0, 100,   0]],

[[  0,   0,  88,   0,   0],
[  0,   0,   0,   0,   0]]])
``````