【问题标题】:Agglomerate adjecent cells and their neighbours of the same type to clusters with python使用python将相邻单元及其相同类型的邻居聚集到集群中
【发布时间】:2021-05-24 16:33:34
【问题描述】:

我正在尝试通过将具有相同类型(从 1 到 10 的整数)的相邻单元(及其邻居)分配给集群 ID 来将它们聚集到新集群中。

如下图所示,一些集群:

目前,我使用广度优先搜索的缩写来遍历所有邻居及其邻居,然后将 cluster-id 分配给所有找到的相同类型的邻居。由于我的数据集相当大(

我在循环中运行的函数偶然选择单元格,直到所有单元格都被分配了一个集群 ID:

def bfs(df, grid_id):
    visited = []
    queue = []
    visited.append(grid_id)
    queue.append(grid_id)
    base_pred = df.loc[grid_id, "class"]
    while queue:
        _ = queue.pop(0)
        n, e = get_n_e_index(grid_id)
        neighbours = get_same_neighbours(base_pred, n, e, agglo_df)
        for neighbour in neighbours:
            if neighbour not in visited:
                visited.append(neighbour)
                queue.append(neighbour)
                queue = queue + get_same_neighbours(base_pred, n, e, agglo_df)

    return visited

visited用于分配相同的cluster_id

get_same_neighbours 只返回给定单元格的具有相同类型的邻居

在我最终验证该方法之前,我得出的结论是它最终会变慢,并且想知道是否有人知道足够快的算法来解决这个问题。在线搜索解决方案没有帮助。

编辑:花了这么长时间不是算法的问题,但我忘记将可能的起始单元格减少到只有那些以前没有被触及过的单元格。

编辑2

get_n_e_index 只是将字符串 ID 转换为东北整数

def get_same_neighbours(base_class, north, east, df):
    neighbours = []
    grid_ids = df["ids"].values
    for i in [-1, 1, 0]:
        for j in [-1, 1, 0]:
            n = int(north + i)
            e = int(east + j)
            grid_id = get_grid_id(n, e)
            invalid = [(-1, 1), (1, 1), (0, 0), (1, -1), (-1, -1)] # invalid combinations
            if grid_id in grid_ids and (j, i) not in invalid and base_class == df.loc[grid_id, "class"]:
                neighbours.append(grid_id)
    return neighbours

get_grid_id 将北 (n) 和东 (e) 整数转换为网格单元的字符串 id。

【问题讨论】:

  • 300 万个网格单元看起来并不是一个很大的数字。图像有几百万像素,这种操作即使是基本的图像编辑软件也可以在几秒钟内完成。即使网格人口稀少,通过迭代网格维度和检查单元邻居的详尽搜索也应该足够快。
  • 无论如何,您的内部循环中有一个隐藏的线性搜索:if neighbour not in visited。您需要使用集合而不是列表。
  • 你的内部循环的最后一行对我来说没有意义,你正在将当前单元格的邻居一个一个地添加到队列中,并为每个单元格添加整个邻居集邻居。
  • 抱歉,我的 while 循环中有一个错误,导致它遍历每个单元格,即使有些单元格可能已经被分配了一个集群。现在所有人都需要4个小时。似乎还是有什么不对劲。最后一行将当前查看的添加邻居的邻居添加到队列中。如果不是,我不明白我实际上做了什么..

标签: python algorithm cluster-analysis


【解决方案1】:

你犯了几个错误。请注意,对于大约 300 万个单元,这应该会在大约一秒钟内起作用。

正如 cmets 中所指出的,visited 应该是用于 O(1) 查找的集合。

其次,如果队列变得很长,queue = queue + get_same_neighbours(base_pred, n, e, agglo_df) 会变得非常慢,因为它会创建队列的副本。相反,只需 append 新项目。

最后,您的queue 实际上不是一个队列,而是一个列表。因此,弹出第一个元素需要O(n) 时间。相反,您可以使用队列(python 中的deque),或者您可以弹出最后一个元素,这会将广度优先搜索变成深度优先搜索,这应该也可以工作。

除此之外,我认为唯一剩下的问题是图形/网格表示。将其存储为数据框似乎通常需要解析整个数据框以查找单元格。如果将其存储为多维数组(无论是lists 还是numpy arrays),甚至是dict,您都可以在O(1) 时间内找到任何单元格。因此,我建议首先将数据帧中的数据预处理为另一个可以轻松访问的数据结构。

【讨论】:

  • 我在编辑中添加了解释/两个 get 函数的代码,因为我觉得我可以在这里学到很多东西。实施 deque 和 set() 将所有单元格的时间减少到大约 4 小时...
  • @Phil 我根据您的编辑编辑了一个段落。我认为剩下的问题是由于 DF 表示。
猜你喜欢
  • 2019-05-30
  • 2019-05-16
  • 2015-09-03
  • 2013-08-05
  • 1970-01-01
  • 2014-01-28
  • 2020-07-08
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多