How to group elements of a numpy array with the same value in separate numpy arrays

Like regular input, I am a dash in python. However, I got a pretty big project for coding. This is a surface flow model with Cell Automata. Anyway, I also want to include building roofs in my model. Imagine you have an ascii file designating buildings with 1s, and the rest is 0. There are only these two states. Now I want to find all the neighboring cells indicating the same building, and save them (more precisely, information about y, x and another (possibly elevation), so there are 3 columns) in separate arrays of buildings. Keep in mind that buildings can have all possible shapes, although diagonally connected cells do not belong to the same building. Thus, only the north, south, west and east cells can belong to the same building.

I did my homework and searched for it, but so far I have not been able to find a satisfactory answer.

Example: source land cover array:

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

(I now need the coordinates of the cells in my source array):

 building_1=([1,2],[2,1],[2,2],[2,3],[3,1],[3,3])
 building_2=([2,5],[2,6],[3,6])

Any help is much appreciated!

+4
source share
3 answers

You can use the labelfrom function scipy.ndimageto identify individual buildings.

Here is your array of examples containing two buildings:

In [57]: a
Out[57]: 
array([[0, 0, 0, 0, 0, 0, 0],
       [0, 0, 1, 0, 0, 0, 0],
       [0, 1, 1, 1, 0, 1, 1],
       [0, 1, 0, 1, 0, 0, 1],
       [0, 0, 0, 0, 0, 0, 0]])

Import label.

In [58]: from scipy.ndimage import label

Apply labelto a. It returns two values: an array of marked positions and the number of individual objects (buildings in this case).

In [59]: lbl, nlbls = label(a)

In [60]: lbl
Out[60]: 
array([[0, 0, 0, 0, 0, 0, 0],
       [0, 0, 1, 0, 0, 0, 0],
       [0, 1, 1, 1, 0, 2, 2],
       [0, 1, 0, 1, 0, 0, 2],
       [0, 0, 0, 0, 0, 0, 0]], dtype=int32)

In [61]: nlbls
Out[61]: 2

To get the coordinates of the building, you can use np.where. For instance,

In [64]: np.where(lbl == 2)
Out[64]: (array([2, 2, 3]), array([5, 6, 6]))

; k - k - . , , np.column_stack, :

 In [65]: np.column_stack(np.where(lbl == 2))
 Out[65]: 
 array([[2, 5],
        [2, 6],
        [3, 6]])

. .

:

In [66]: labels = range(1, nlbls+1)

In [67]: labels
Out[67]: [1, 2]

.

In [68]: coords = [np.column_stack(where(lbl == k)) for k in labels]

In [69]: coords
Out[69]: 
[array([[1, 2],
       [2, 1],
       [2, 2],
       [2, 3],
       [3, 1],
       [3, 3]]),
 array([[2, 5],
       [2, 6],
       [3, 6]])]

labels coords. , labels[0], coords[0]:

In [70]: labels[0]
Out[70]: 1

In [71]: coords[0]
Out[71]: 
array([[1, 2],
       [2, 1],
       [2, 2],
       [2, 3],
       [3, 1],
       [3, 3]])
+5

! . , 0 , -9999 (0 ). . , -9999 0 landcover = np.where(a > -9999, landcover, 0). . , . - , , !

import numpy as np
from scipy.ndimage import label

-9999 , 1 - .

landcover = np.array([[-9999,-9999,-9999,-9999,-9999,-9999,1], 
                       [-9999,-9999,1,-9999,-9999,-9999,-9999],
                       [-9999,1,1,1,-9999,1,1], 
                       [-9999,1,-9999,1,-9999,-9999,1], 
                       [-9999,-9999,-9999,-9999,-9999,-9999,-9999]],dtype=int)

.

DEM = np.array([[7,4,3,2,4,5,4], 
               [4,5,5,3,5,6,7],
               [2,6,4,7,4,4,4],
               [3,7,8,8,10,9,7],
               [2,5,7,7,9,10,8]],dtype=float)

-9999 0, @thanks

 landcover = np.where(landcover > -9999, landcover, 0)

@Warren Weckesser, . !

 lbl, nlbls = label(landcover)
 bldg_number = range(1, nlbls+1)
 bldg_coord = [np.column_stack(where(lbl == k)) for k in bldg_no]
 outlets=np.zeros([nlbls,3])

bldg_coord, ,

 for i in range(0, nlbls):
     building=np.zeros([bldg_coord[i].shape[0],3])
     for j in range(0,bldg_coord[i].shape[0]):
         building[j][0]=bldg_coord[i][j][0]
         building[j][1]=bldg_coord[i][j][1]
         building[j][2]=DEM[bldg_coord[i][j][0],bldg_coord[i][j][1]]

DEM , .

  building=building[building[:,2].argsort()]

  outlets[i][0]=building[0][0]
  outlets[i][1]=building[0][1]
  outlets[i][2]=bldg_coord[i].shape[0]

. - den, - .

>>> outlets
array([[ 0.,  6.,  1.],
       [ 2.,  2.,  6.],
       [ 2.,  5.,  3.]])
+1

, , ( numpy):

numpy.argwhere():

, , .

>>> x = np.arange(6).reshape(2,3)
>>> x
array([[0, 1, 2],
       [3, 4, 5]])
>>> np.argwhere(x>1)
array([[0, 2],
       [1, 0],
       [1, 1],
       [1, 2]])

, .

The output argwhere file is not suitable for indexing arrays. To do this, use where (a).

You can try it instead numpy.where.

0
source

Source: https://habr.com/ru/post/1534983/


All Articles