如何在单独的numpy数组中使用相同的值对numpy数组的元素进行分组

Scr*_*rox 5 python grouping numpy

像往常一样介绍,我是python中的tyro.但是,我有一个很大的代码项目.它是Cell Automata的表面流动模型.无论如何,我还想在我的模型中包括建筑屋顶.想象一下,你有一个ascii文件指示1s的建筑物,而其余的是0.只有这两种状态.现在,我想找到所有相邻的单元格,指示相同的建筑物并将它们(或者更确切地说是y,x和另外一个(可能是高程)的信息,因此在单个建筑物阵列中存储).请记住,尽管对角连接的单元不属于同一建筑物,但建筑物可以具有所有可能的形式.因此,只有北部,南部,西部和东部的细胞可以属于同一建筑物.

我做了我的作业并用谷歌搜索了它,但到目前为止我找不到令人满意的答案.

示例:初始土地覆盖数组:

([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])
Run Code Online (Sandbox Code Playgroud)

输出(我现在需要初始数组中单元格的坐标):

 building_1=([1,2],[2,1],[2,2],[2,3],[3,1],[3,3])
 building_2=([2,5],[2,6],[3,6])
Run Code Online (Sandbox Code Playgroud)

任何帮助是极大的赞赏!

War*_*ser 5

您可以使用此label功能scipy.ndimage来识别不同的建筑物.

这是你的示例数组,包含两个建筑物:

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]])
Run Code Online (Sandbox Code Playgroud)

导入label.

In [58]: from scipy.ndimage import label
Run Code Online (Sandbox Code Playgroud)

适用labela.它返回两个值:标记位置数组,以及找到的不同对象(在本例中为建筑物)的数量.

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
Run Code Online (Sandbox Code Playgroud)

要获得建筑物的坐标,np.where可以使用.例如,

In [64]: np.where(lbl == 2)
Out[64]: (array([2, 2, 3]), array([5, 6, 6]))
Run Code Online (Sandbox Code Playgroud)

它返回一个数组元组; 所述k第阵列保持的坐标k个维度.例如,您可以np.column_stack将这些组合成一个数组:

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

您可能需要所有坐标数组的列表.这是创建这样一个列表的一种方法.

为方便起见,首先要创建一个标签列表:

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

In [67]: labels
Out[67]: [1, 2]
Run Code Online (Sandbox Code Playgroud)

使用列表推导来创建坐标数组列表.

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]])]
Run Code Online (Sandbox Code Playgroud)

现在你的建筑数据在labelscoords.例如,标记了第一个建筑物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]])
Run Code Online (Sandbox Code Playgroud)