如何将具有相同值的numpy数组的元素分组到单独的numpy数组中

2024-05-17 02:37:04 发布

您现在位置:Python中文网/ 问答频道 /正文

和往常一样,我是一个python中的tyro。然而,我有一个相当大的项目代码。它是一个带有细胞自动机的表面流模型。无论如何,我也希望在我的模型中包含建筑屋顶。假设您有一个ascii文件,它指示带有1的建筑物,而其余的是0。只有这两个州。现在,我想找到所有指示同一建筑的相邻单元,并将它们(或者更确切地说是y、x和一个以上(可能是立面)的信息,即3列)存储在单个建筑阵列中。请记住,尽管对角线连接的单元不属于同一个建筑,但建筑可以有所有可能的形式。所以只有北、南、西、东三个单元可以属于同一个建筑。

我做了家庭作业并用谷歌搜索了一下,但到目前为止我找不到满意的答案。

示例: 初始土地覆盖阵列:

([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])

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

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

非常感谢您的帮助!


Tags: 文件项目代码模型信息自动机ascii表面
3条回答

看起来这个函数做的正是您想要的(从the numpy documentation):

numpy.argwhere(a):

Find the indices of array elements that are non-zero, grouped by element.

>>> 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 of argwhere is not suitable for indexing arrays. For this purpose use where(a) instead.

您可能需要尝试numpy.where

您可以使用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]])

导入label

In [58]: from scipy.ndimage import label

label应用到a。它返回两个值:标记位置的数组和找到的不同对象(在本例中是建筑物)的数量。

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

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

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]])]

现在你的建筑数据在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]])

谢谢你的回答!这里有一点修正。如果你看到土地覆盖阵列,我实际上没有0作为背景信息,但-9999(0对地理信息系统的人来说太宝贵了)。我忘了提那件事。但多亏了机器渴望的提示,我做了一个变通,通过landcover=np.where(landcover>;-9999,landcover,0)给all-9999分配了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)

由于机器的渴望,为了使用label@

 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])

我正在遍历建筑坐标列表,以确定分配为出口的最低单元

 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 landcover数组中的索引,最后一列是相邻建筑单元的数量。

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

相关问题 更多 >