如何在numpy.array中以热量方式将numpy.array传递给对象的方法

问题描述 投票:2回答:2

我有一个包含字符串的2d numpy数组txtStrs,我将其作为文本写入matplotlib数字轴ax,使用例如

ax.text( posX, posY, txtStrs[0,0] )

后来,我想更新这些文本(相同的位置,颜色等)而不重新绘制整个图形。因此,我将文本对象保存到另一个numpy数组中。

当我现在想要更新文本时,我使用了两个for循环

    import numpy as np
    import matplotlib.pyplot as plt
    siz = 20

    txtStrs = np.empty( (siz, siz), dtype = str )
    txtObjs = np.empty( (siz, siz), dtype = object )

    plt.figure()
    ax = plt.gca()
    for x in range(siz):
        for y in range(siz)):
            txtObjs[x,y] = ax.text( x, y, "" )

    #Fill txtStrs with some string values

    for x in range(siz):
        for y in range(siz)):
            txtObjs[x,y].set_text( txtStrs[x,y] )

最后一个for循环似乎是不必要的,对我来说并不是真正的pythonic。如果我不需要调用set_text方法,我可以使用numpy的内在理解来进行更新。

我的问题是:是否有另一种方法将txtStrs传递给txtObjs,例如使用vectorize,list-comprehension还是其他什么?

python numpy matplotlib iteration
2个回答
2
投票

循环是Pythonic!

并且使用set_text对象的matplotlib.text方法也是有效的Python。这就是我们使用对象的方式 - 使用他们的方法。

使用numpy我们尝试避免循环,但如果数组包含数字(或字符串)dtypes,那只是节省大量时间。然后它可以使用提供的数组方法在已编译的代码中进行迭代。你的txtObjs数组是对象dtype,并且这种数组上的大多数操作都涉及Python级迭代,即使它是隐藏的。像列表一样,对象数组包含指向内存中其他对象的指针。它必须引用每个对象并使用自己的方法。

对象数组的迭代比列表上的迭代慢一点,尽管数组的多维特性可以使迭代更漂亮。

列表理解是编写for循环的一种巧妙方式 - 如果您要返回一个新列表。它不适用于就地修改。对于“矢量化”(隐藏)迭代的一些numpy函数也是如此。

如果txtObjstxtStrs是相同大小的列表,那么

for a, b in zip(txtObjs, txtStrs):
    a.set_text(b)

应该更新所有text对象。

对于2D阵列:

for a, b in zip(txtObjs.ravel(), txtStrs.ravel()):

也应该工作。这些数组的2d形状妨碍了简单地传递值,尽管设置初始坐标可能很方便。


2
投票

这是将这两个循环减少到只有一个的东西,但我并不认为存在“apply”,“forEach”或类似的东西。

for (x, y), text_obj in np.ndenumerate(txtObjs):
    text_obj.set_text(txtStrs[x, y])

这使用ndenumerate,这是一种迭代通过n维numpy数组的巧妙方法。

© www.soinside.com 2019 - 2024. All rights reserved.