【问题标题】:Apply function to 2D numpy array elements将函数应用于 2D numpy 数组元素
【发布时间】:2016-08-10 23:00:52
【问题描述】:

我看过这个post 并想做类似的事情,但不完全相同。

我正在实现一个小生活游戏游戏,并使用numpy arrays 表示游戏的状态。所以我需要检查一个cell有多少个活着的邻居。我已经有了一个函数,可以在给定我想要的窗口大小的坐标、行数和列数的情况下获取 邻居窗口

所以通常我的窗户是这样的 3x3 大小:

T = True
F = False
[[T,T,T],
 [F,T,T],
 [F,F,F]]  # some random truth values

在这个表示中,True 代表一个细胞是活着的。 现在我编写了一些代码迭代状态的所有单元格,使用双 for 循环计算 True 值等等,但我认为可能有更好的 numpy 解决方案。

我会在幼稚的方法中做什么:

  1. 遍历状态的所有单元格(不仅是窗口)(我想制定一些代码以在单元格满足标准或其他条件时执行(活着并存活或死亡并活着))
  2. 获取窗口(包装或不包装)(我已经拥有的功能)
  3. 检查当前单元格是否处于活动状态(可以在状态的 numpy 数组中查找)
  4. 如果它是活着的,则从活着的邻居计数 -1 开始,否则从 0 开始
  5. 计算窗口的所有 True 值 (np.sum) 并将其添加到活着的邻居计数中(如果单元格本身还活着,则为 -1,因此我只计算邻居而不是单元格本身)
  6. 根据存活邻居的数量是否在特定范围内(可配置),写入另一个(新)状态的数组True 值。 (我会从一个数组开始,我使用以下方法创建:np.full((height, width), False, dtype=bool)
  7. 继续使用新数组,将旧数组保留在列表中以供历史记录或记录目的

基本上:

if cell meets criteria:
    write True at the cell's position in a new array

但是满足条件取决于多行,因为状态的 numpy 数组是二维数组。这就是为什么我认为链接的帖子很接近但不完全是我需要的。

我怎样才能以一种有效的 numpy-y 方式做到这一点,避免不必要的循环?

澄清

我正在寻找在 python 中使用 numpy 和 scipy 实现这一点的最佳方法,它的目标是可读性强并具有良好的性能。

【问题讨论】:

  • 编写一个明确但清晰地完成所有迭代的版本。并给我们一个测试用例来使用它。然后我们可以帮助简化它,最有可能从最内层循环开始,您可以在其中执行sum
  • 您可以使用 scipy.ndimage.filters 轻松完成此操作,窗口大小为 3。将 True 视为 1 并将 False 视为 0,generic_filter 可能与function=lambda a: 1 if a.sum() - a[4] > 4 else 0 一起工作。但是如果没有明确的输入/输出示例,就很难说。

标签: python numpy


【解决方案1】:

也许我不明白你想要做什么,但是是什么阻止你简单地使用 numpy.sum 函数?

示例 - 让状态为:

import numpy as np
state = np.random.randint(1, 10, (9,9))

这里我使用 {0, 1} 作为状态值,其中 1 表示“活着”。 然后你可以在被调查的细胞周围切片,例如[2,3]

s = state[1:3,2:5]
if s[1,1]:
   val = -1
else
   val = 0
val += s.sum()

如果你把它放在一个 for 循环中并注意边界情况,适当的夹紧或换行,它应该按照你的描述做。

如果您正在寻找一个简短的优雅实现,可以非常efficiently with Python and Numpy

【讨论】:

  • 到目前为止听起来不错。我只想避免循环遍历所有单元格和每次迭代切片等 - 如果这是可能的。该链接:D 我应该在开始之前搜索类似解决方案的东西......我会检查它,看看我是否可以采用代码。
  • 问题中隐含了循环:最后你必须对邻居的值求和。即使是链接中非常优雅的代码也使用了带有嵌套循环的生成器表达式,它必须以一种或另一种方式执行。
  • Cybr...,您将 s 视为嵌套列表,而不是数组。
  • @hpaulj 真的!把我的语法弄混了(在 C 中编程太多了 :),谢谢并修复。
  • 我在想你也想做一些布尔掩码,但你只测试s 中的一项。这样if 就可以了(val = -1 if s[1,1] else 0 是次要的选择)。
猜你喜欢
  • 1970-01-01
  • 2020-06-06
  • 1970-01-01
  • 2016-08-19
  • 1970-01-01
  • 2019-07-25
  • 2020-08-16
  • 2017-11-29
  • 2014-04-20
相关资源
最近更新 更多