首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >numpy数组指示符操作

numpy数组指示符操作
EN

Stack Overflow用户
提问于 2018-05-30 07:22:12
回答 3查看 714关注 0票数 4

我想通过给定的指示器(x和y轴)修改一个空位图。对于指示器给出的每个坐标,该值应增加1。

到目前为止,一切似乎都很顺利。但是如果我在我的指标数组中有一些类似的指标,它只会增加一次值。

>>> img
array([[0, 0, 0, 0, 0],
       [0, 0, 0, 0, 0],
       [0, 0, 0, 0, 0],
       [0, 0, 0, 0, 0],
       [0, 0, 0, 0, 0]])

>>> inds
array([[0, 0],
       [3, 4],
       [3, 4]])

操作:

>>> img[inds[:,1], inds[:,0]] += 1

结果:

>>> img
    array([[1, 0, 0, 0, 0],
           [0, 0, 0, 0, 0],
           [0, 0, 0, 0, 0],
           [0, 0, 0, 0, 0],
           [0, 0, 0, 1, 0]])

预期结果:

>>> img
    array([[1, 0, 0, 0, 0],
           [0, 0, 0, 0, 0],
           [0, 0, 0, 0, 0],
           [0, 0, 0, 0, 0],
           [0, 0, 0, 2, 0]])

有人知道怎么解决这个问题吗?最好是一种不使用循环的快速方法。

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2018-05-30 08:42:15

关于其他两个答案的两点备注:

1) @jpp可以通过使用带有axisreturn_counts关键字的np.unique来改进。

2)如果我们转换为平面索引,我们可以使用比np.add.at更快的np.bincount (但不总是,参见基准测试中的最后一个测试用例)。

感谢@miradulo提供的基准测试的初始版本。

import numpy as np

def jpp(img, inds):
    counts = (inds[:, None] == inds).all(axis=2).sum(axis=1)
    img[inds[:,1], inds[:,0]] += counts

def jpp_pp(img, inds):
    unq, cnts = np.unique(inds, axis=0, return_counts=True)
    img[unq[:,1], unq[:,0]] += cnts

def miradulo(img, inds):
    np.add.at(img, tuple(inds[:, [1, 0]].T), 1)

def pp(img, inds):
    imgf = img.ravel()
    indsf = np.ravel_multi_index(inds.T[::-1], img.shape[::-1])
    imgf += np.bincount(indsf, None, img.size)

inds = np.random.randint(0, 5, (3, 2))
big_inds = np.random.randint(0, 5, (10000, 2))
sml_inds = np.random.randint(0, 1000, (5, 2))
from timeit import timeit


for f in jpp, jpp_pp, miradulo, pp:
    print(f.__name__)
    for i, n, a in [(inds, 1000, 5), (big_inds, 10, 5), (sml_inds, 10, 1000)]:
        img = np.zeros((a, a), int)
        print(timeit("f(img, i)", globals=dict(img=img, i=i, f=f), number=n) * 1000 / n, 'ms')

输出:

jpp
0.011815106990979984 ms
2623.5026352020213 ms
0.04642329877242446 ms
jpp_pp
0.041291153989732265 ms
5.418520100647584 ms
0.05826510023325682 ms
miradulo
0.007099648006260395 ms
0.7788308983435854 ms
0.009103797492571175 ms
pp
0.0035401539935264736 ms
0.06540440081153065 ms
3.486583800986409 ms
票数 4
EN

Stack Overflow用户

发布于 2018-05-30 07:27:37

这是一种方法。计数算法courtesy of @AlexRiley

有关imginds的相对大小的性能影响,请参阅@PaulPanzer's answer

# count occurrences of each row and return array
counts = (inds[:, None] == inds).all(axis=2).sum(axis=1)

# apply indices and counts
img[inds[:,1], inds[:,0]] += counts

print(img)

array([[1, 0, 0, 0, 0],
       [0, 0, 0, 0, 0],
       [0, 0, 0, 0, 0],
       [0, 0, 0, 0, 0],
       [0, 0, 0, 2, 0]])
票数 6
EN

Stack Overflow用户

发布于 2018-05-30 07:41:56

您可以使用带有一些操作的numpy.add.at来准备索引。

np.add.at(img, tuple(inds[:, [1, 0]].T), 1)

如果你有更大的inds数组,这种方法应该保持快速...(虽然Paul Panzer's solution更快)

票数 5
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/50594318

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档