1

Given a numpy matrix, my_matrix.

import numpy as np

my_matrix = np.array([[1.2,2.3,None],[4.5,3.4,9.3]])

How can you efficiently flatten it into the following array containing the index positions of my_matrix?

[[0,0],[0,1],[0,2],[1,0],[1,1],[1,2]]
Eric
  • 795
  • 5
  • 21
  • I have seen [this](https://stackoverflow.com/questions/31081067/flatten-numpy-array-but-also-keep-index-of-value-positions) question however I'm not looking to create a dataframe. – Eric Aug 21 '19 at 20:32
  • 1
    How is the content of `my_matrix` important? The index list you provided would be valid for each 2x3 matrix, right? – Samufi Aug 21 '19 at 20:34
  • And: Do you need the resulting index list for indexing? If so, there may be a more efficient alternative approach. – Samufi Aug 21 '19 at 20:36
  • The matrix contains values that in obtained from a .tif file imported from the [rasterio](https://rasterio.readthedocs.io/en/stable/) package. I would like to [map a function](https://stackoverflow.com/questions/35215161/most-efficient-way-to-map-function-over-numpy-array) on the array of index locations which will return an array of lat and lon positions. – Eric Aug 21 '19 at 20:41
  • If you want to literally `map` a function, it may be beneficial to use a generator for the indices rather than using a list. – Samufi Aug 21 '19 at 20:42
  • 1
    Thanks, but I've never used a generator. rusu_ro1s solution is working well for my use case. `[func_pixle_to_coords(jj, ii) for ii in range(rows) for jj in range(cols)]` – Eric Aug 21 '19 at 20:55

3 Answers3

1

you can try:

rows, cols = my_matrix.shape
[[i, j] for i in range(rows) for j in range(cols)]

output:

[[0, 0], [0, 1], [0, 2], [1, 0], [1, 1], [1, 2]]
kederrac
  • 16,819
  • 6
  • 32
  • 55
0

You can use numpy.indices() and reshape the returned values a little bit

np.indices(my_matrix.shape).transpose(1, 2, 0).reshape(-1, 2)
# array([[0, 0],
#        [0, 1],
#        [0, 2],
#        [1, 0],
#        [1, 1],
#        [1, 2]])
Nils Werner
  • 34,832
  • 7
  • 76
  • 98
0

You can create such a list easily with pure python:

from itertools import product
list(product(range(my_matrix.shape[0]), range(my_matrix.shape[1])))

Result is

[(0, 0), (0, 1), (0, 2), (1, 0), (1, 1), (1, 2)]

If you are not using the explicit list but only want to iterate over the indices, leave the list(...) away. This will save memory and computation time, as the indices will be generated when they are used only.

However, if you want to use the result to index a numpy array, it may be more convenient to use np.ix_:

np.ix_(np.arange(my_matrix.shape[0]), np.arange(my_matrix.shape[1]))

Output is

(array([[0],
        [1]]), array([[0, 1, 2]]))
Samufi
  • 2,465
  • 3
  • 19
  • 43