Reputation: 383
Assume the next dictionary is given:
{(0, 0): 1, (1, 1): 12, (2, 2): 802, (3, 3): 1687, (4, 4): 11, (5, 4): 4, (6, 5): 593, (7, 4): 4}
In the dictionary above each key displays a point in the matrix (x, y)
and a value displays the value found in the matrix. How could I construct an array that will contain the values located at each point x
, y
?
According to the dictionary above the expected result is:
array([[ 1, 0, 0, 0, 0, 0],
[ 0, 12, 0, 0, 0, 0],
[ 0, 0, 802, 0, 0, 0],
[ 0, 0, 0, 1687, 0, 0],
[ 0, 0, 0, 0, 11, 0],
[ 0, 0, 0, 0, 4, 0],
[ 0, 0, 0, 0, 0, 593],
[ 0, 0, 0, 0, 4, 0]])
Upvotes: 2
Views: 1136
Reputation: 5949
The most efficient way of extracting values of any iterable in pure numpy is np.fromiter
. And here is a good occasion to use it:
Approach 1
d = {(0, 0): 1, (1, 1): 12, (2, 2): 802, (3, 3): 1687, (4, 4): 11, (5, 4): 4, (6, 5): 593, (7, 4): 4}
X = np.zeros((8,8), dtype=int)
idx = np.fromiter(d, dtype='i,i').view(int).reshape(-1, 2)
vals = np.fromiter(d.values(), dtype=float)
X[idx[:,0], idx[:,1]] = vals
Remark: I mean extracting values of iterable that corresponds to some shape. itertools.chain
is needed in addition otherwise.
Approach 2
itertools.chain
is a very fast way to flatten iterables which gives a significant boost to np.fromiter
. It has no requirements for sizes of iterable items. This works 2.5x times faster than previous alternative:
import itertools
X = np.zeros((8,8), dtype=int)
idx = np.fromiter(itertools.chain(*d.keys()), dtype=int).reshape(-1,2)
vals = np.fromiter(d.values(), dtype=float)
X[idx[:,0], idx[:,1]] = vals
Approach 3
zip
could be used instead of itertools.chain
but it still little bit (5-10%) slower than approach 2:
X = np.zeros((8,8), dtype=int)
idx1, idx2 = zip(*d.keys())
vals = np.fromiter(d.values(), dtype=float)
X[idx1, idx2] = vals
Upvotes: 1
Reputation: 88285
You could use np.add.at
, defining the shape of the array beforehand from the keys:
d = {(0, 0): 1, (1, 1): 12, (2, 2): 802, (3, 3): 1687, (4, 4): 11,
(5, 4): 4, (6, 5): 593, (7, 4): 4}
i,j = zip(*d.keys())
a = np.zeros((max(i)+1,max(j)+1), np.int32)
np.add.at(a, tuple((i,j)), tuple(d.values()))
a
array([[ 1, 0, 0, 0, 0, 0],
[ 0, 12, 0, 0, 0, 0],
[ 0, 0, 802, 0, 0, 0],
[ 0, 0, 0, 1687, 0, 0],
[ 0, 0, 0, 0, 11, 0],
[ 0, 0, 0, 0, 4, 0],
[ 0, 0, 0, 0, 0, 593],
[ 0, 0, 0, 0, 4, 0]])
Upvotes: 2
Reputation: 14399
That's just a dictionary of keys (dok
) representation for sparse matrices. So . . .
from scipy.sparse import dok_matrix
out = dok_matrix((8, 8), dtype = int)
out._update(d)
out.todense()
Out[]:
matrix([[ 1, 0, 0, 0, 0, 0, 0, 0],
[ 0, 12, 0, 0, 0, 0, 0, 0],
[ 0, 0, 802, 0, 0, 0, 0, 0],
[ 0, 0, 0, 1687, 0, 0, 0, 0],
[ 0, 0, 0, 0, 11, 0, 0, 0],
[ 0, 0, 0, 0, 4, 0, 0, 0],
[ 0, 0, 0, 0, 0, 593, 0, 0],
[ 0, 0, 0, 0, 4, 0, 0, 0]])
Upvotes: 1
Reputation: 574
Try this
import numpy as np
matrix = np.zeros((8,6))
your_dict = {(0, 0): 1, (1, 1): 12, (2, 2): 802, (3, 3): 1687, (4, 4): 11, (5,4): 4, (6, 5): 593, (7, 4): 4}
for key, value in your_dict.items():
matrix[key[0],key[1]] = value
In case your matrix is other size consider changing the zeros initialization
Output
[[ 1 0 0 0 0 0]
[ 0 12 0 0 0 0]
[ 0 0 802 0 0 0]
[ 0 0 0 1687 0 0]
[ 0 0 0 0 11 0]
[ 0 0 0 0 4 0]
[ 0 0 0 0 0 593]
[ 0 0 0 0 4 0]]
Upvotes: 0
Reputation: 8318
Yet another solution is:
import numpy as np
d = {(0, 0): 1, (1, 1): 12, (2, 2): 802, (3, 3): 1687, (4, 4): 11, (5, 4): 4, (6, 5): 593, (7, 4): 4}
X = np.zeros((8,8))
X[tuple(np.array(list(d.keys())).T)] = list(d.values())
Which output:
array([[ 1, 0, 0, 0, 0, 0, 0, 0],
[ 0, 12, 0, 0, 0, 0, 0, 0],
[ 0, 0, 802, 0, 0, 0, 0, 0],
[ 0, 0, 0, 1687, 0, 0, 0, 0],
[ 0, 0, 0, 0, 11, 0, 0, 0],
[ 0, 0, 0, 0, 4, 0, 0, 0],
[ 0, 0, 0, 0, 0, 593, 0, 0],
[ 0, 0, 0, 0, 4, 0, 0, 0]], dtype=uint32)
Use tuple of numpy
arrays which can be directly passed to the matrix to get the elements and then assign the values of the dictionary.
Upvotes: 0
Reputation: 10624
My 2cents:
n=np.zeros([max(d.keys(), key=lambda x:x[0])[0]+1,max(d.keys(), key=lambda x:x[1])[1]+1], int)
for i,k in d.items():
n[i[0], i[1]]=k
>>>print(n)
array([[ 1, 0, 0, 0, 0, 0],
[ 0, 12, 0, 0, 0, 0],
[ 0, 0, 802, 0, 0, 0],
[ 0, 0, 0, 1687, 0, 0],
[ 0, 0, 0, 0, 11, 0],
[ 0, 0, 0, 0, 4, 0],
[ 0, 0, 0, 0, 0, 593],
[ 0, 0, 0, 0, 4, 0]])
Upvotes: 1
Reputation: 61920
Use a coo sparse matrix and convert to array afterwards:
from scipy.sparse import coo_matrix
data= {(0, 0): 1, (1, 1): 12, (2, 2): 802, (3, 3): 1687, (4, 4): 11, (5, 4): 4, (6, 5): 593, (7, 4): 4}
row, col, fill = zip(*[(*k, v) for k, v in data.items()])
result = coo_matrix((fill, (row, col)), shape=(8, 6)).toarray()
print(result)
Output
[[ 1 0 0 0 0 0]
[ 0 12 0 0 0 0]
[ 0 0 802 0 0 0]
[ 0 0 0 1687 0 0]
[ 0 0 0 0 11 0]
[ 0 0 0 0 4 0]
[ 0 0 0 0 0 593]
[ 0 0 0 0 4 0]]
Upvotes: 1
Reputation: 484
import numpy as np
cols = max(key[0] for key in d) + 1
rows = max(key[1] for key in d) + 1
mat = np.zeros((cols, rows), dtype=np.int)
for point in d: mat[point] = d[point]
print(mat)
####### result #######
[[ 1 0 0 0 0 0]
[ 0 12 0 0 0 0]
[ 0 0 802 0 0 0]
[ 0 0 0 1687 0 0]
[ 0 0 0 0 11 0]
[ 0 0 0 0 4 0]
[ 0 0 0 0 0 593]
[ 0 0 0 0 4 0]]
Upvotes: 0
Reputation: 11927
If the array size is known already, you can do this,
import numpy as np
arr = np.zeros((8, 6), dtype='int')
d = {(0, 0): 1, (1, 1): 12, (2, 2): 802, (3, 3): 1687, (4, 4): 11, (5, 4): 4, (6, 5): 593, (7, 4): 4}
for key, val in d.items():
arr[key[0]][key[1]] = val
array([[ 1, 0, 0, 0, 0, 0],
[ 0, 12, 0, 0, 0, 0],
[ 0, 0, 802, 0, 0, 0],
[ 0, 0, 0, 1687, 0, 0],
[ 0, 0, 0, 0, 11, 0],
[ 0, 0, 0, 0, 4, 0],
[ 0, 0, 0, 0, 0, 593],
[ 0, 0, 0, 0, 4, 0]])
Upvotes: 0