我有一个二维的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
,例如使用矢量化,列表理解还是其他方法?
答案 0 :(得分:2)
这里有些东西可以将这两个循环减少到一个,但是我真的不认为有一个“ apply”,“ forEach”之类的东西。
for (x, y), text_obj in np.ndenumerate(txtObjs):
text_obj.set_text(txtStrs[x, y])
这使用ndenumerate,这是遍历n维numpy数组的一种巧妙方法。
答案 1 :(得分:2)
循环是Pythonic!
使用set_text
对象的matplotlib.text
方法也是有效的Python。这就是我们处理对象的方式-使用对象的方法。
我们使用numpy
尝试避免循环,但是如果数组包含数字(或字符串)dtypes,那只会节省大量时间。然后,它可以使用提供的数组方法在编译的代码中进行迭代。您的txtObjs
数组是dtype对象,即使在隐藏状态下,此类数组上的大多数操作都涉及Python级别的迭代。像列表一样,对象数组包含指向内存中其他位置的对象的指针。它必须引用每个对象并使用自己的方法。
对象数组的迭代比列表迭代慢一些,尽管数组的多维性质可以使迭代更漂亮。
列表解析是编写for循环的一种巧妙方法-如果要返回新列表。它不适用于就地修改。某些“向量化”(隐藏)迭代的numpy函数也是如此。
如果txtObjs
和txtStrs
是相同大小的列表,则
for a, b in zip(txtObjs, txtStrs):
a.set_text(b)
应更新所有text
对象。
对于二维数组:
for a, b in zip(txtObjs.ravel(), txtStrs.ravel()):
也应该起作用。尽管可以方便地设置初始坐标,但是这些数组的2d形状妨碍了简单地传递值。