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.
Advertisement
Answer
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]]])