【发布时间】:2018-01-24 08:30:55
【问题描述】:
假设我们有一个这样的二维数组:
>>> a
array([[1, 1, 2],
[0, 2, 2],
[2, 2, 0],
[0, 2, 0]])
对于每一行,我想用同一行中其他 2 个元素中的最大值替换每个元素。
我已经找到了如何使用 numpy.amax 和一个标识数组分别为每一列执行此操作,如下所示:
>>> np.amax(a*(1-np.eye(3)[0]), axis=1)
array([ 2., 2., 2., 2.])
>>> np.amax(a*(1-np.eye(3)[1]), axis=1)
array([ 2., 2., 2., 0.])
>>> np.amax(a*(1-np.eye(3)[2]), axis=1)
array([ 1., 2., 2., 2.])
但我想知道是否有办法避免 for 循环并直接获得结果,在这种情况下应该如下所示:
>>> numpy_magic(a)
array([[2, 2, 1],
[2, 2, 2],
[2, 2, 2],
[2, 0, 2]])
编辑:在控制台中玩了几个小时后,我终于想出了我正在寻找的解决方案。准备好一些令人兴奋的一行代码:
np.amax(a[[range(a.shape[0])]*a.shape[1],:][(np.eye(a.shape[1]) == 0)[:,[range(a.shape[1])*a.shape[0]]].reshape(a.shape[1],a.shape[0],a.shape[1])].reshape((a.shape[1],a.shape[0],a.shape[1]-1)),axis=2).transpose()
array([[2, 2, 1],
[2, 2, 2],
[2, 2, 2],
[2, 0, 2]])
Edit2:Paul 提出了一个更具可读性和更快的替代方案,即:
np.max(a[:, np.where(~np.identity(a.shape[1], dtype=bool))[1].reshape(a.shape[1], -1)], axis=-1)
在对这 3 种备选方案进行计时后,Paul 的两种解决方案在每种情况下都快 4 倍(我已针对 200 行的 2、3 和 4 列进行了基准测试)。恭喜这些令人惊叹的代码!
上次编辑(抱歉):在将 np.identity 替换为更快的 np.eye 之后,我们现在有了最快最简洁的解决方案:
np.max(a[:, np.where(~np.eye(a.shape[1], dtype=bool))[1].reshape(a.shape[1], -1)], axis=-1)
【问题讨论】:
-
我讨厌批评,但 那 是您要找的吗?看,这是一个长度不到一半的可读版本:
np.max(a[:, np.where(~np.identity(a.shape[1], dtype=bool))[1].reshape(a.shape[1], -1)], axis=-1) -
干得好@PaulPanzer!我已经编辑了问题并为你的答案加了星标,即使我更喜欢最后一个,如果你用 np.eye 替换 np.identity 也会更快。非常感谢你!
-
谢谢。我有点惊讶这是最快的,因为根据我的经验,高级索引有点慢。也许是因为它只是少数几个索引。另外,我以前认为
eye和identity本质上是一样的。很多东西要学...