matplotlib 在移动窗口中绘制数值范围

0vvn1miw  于 2023-10-24  发布在  其他
关注(0)|答案(1)|浏览(156)

我想做一个移动窗口,当它在数据中移动时,它会在每个框中绘制值的范围。我一直在做这样的运行窗口:

  1. import numpy as np
  2. from astropy.convolution import convolve
  3. x = np.random.randint(10,size=(10,10))
  4. y = convolve(x,np.ones((5,5)),boundary='extend',preserve_nan=True)
  5. print('x:',x)
  6. print('y:',y)
  7. x: [[0 2 7 7 3 8 0 5 5 7]
  8. [6 8 0 6 2 0 0 0 9 7]
  9. [7 4 4 1 5 1 1 6 1 8]
  10. [8 9 5 2 3 5 4 2 6 5]
  11. [0 7 2 4 3 6 6 6 7 5]
  12. [0 0 8 3 2 8 1 0 7 9]
  13. [5 2 0 6 3 3 0 0 6 0]
  14. [1 0 2 9 7 9 7 6 5 6]
  15. [5 6 5 5 5 3 8 0 6 4]
  16. [5 9 9 5 2 8 1 3 0 6]]
  17. y: [[6.12 6.08 6.2 5.64 5.68 4.72 3.88 3.04 2.88 2.24]
  18. [5.68 5.68 5.76 5.28 5.6 4.76 4. 3.4 3.36 2.8 ]
  19. [5.44 5.24 5.32 4.96 5.16 4.76 4.08 3.44 3.24 2.88]
  20. [5.32 4.96 4.92 4.4 4.6 4.2 3.64 3.08 3. 2.68]
  21. [4.96 4.8 4.92 4.68 4.72 4.4 3.8 3.4 3.36 3.44]
  22. [4.52 4.44 4.52 4.4 4.48 4.24 3.76 3.4 3.24 3.24]
  23. [4.12 4.2 4.36 4.12 3.76 3.8 3.44 3.2 3.36 3.68]
  24. [3.32 3.84 4.24 3.92 3.8 3.76 3.44 3.48 4.24 4.72]
  25. [2.4 3.32 4.08 3.96 3.96 4.28 3.96 4.16 5.24 6.04]
  26. [2.08 3.16 4.32 4.16 4.36 4.6 4.4 4.44 5.8 6.64]]

这会计算每个5x5窗口的平均值,但是有没有办法显示x中的值的范围?比如说一个窗口来自x的左上角:

  1. 0 2 7 7 3
  2. 6 8 0 6 2
  3. 7 4 4 1 5
  4. 8 9 5 2 3
  5. 0 7 2 4 3

范围是从0到9,所以在matplotlib图中,将绘制9,并且这将在数据中移动的每个窗口中重复。因此最终的图看起来像:

0ejtzxu1

0ejtzxu11#

使用mplcursors,可以交互式地标记一个区域,并通过注解显示值。

  1. import matplotlib.pyplot as plt
  2. from matplotlib.patches import Rectangle
  3. import mplcursors
  4. import numpy as np
  5. from astropy.convolution import convolve
  6. def show_rect(sel):
  7. i, j = sel.target.index
  8. i0 = 0 if i - 2 < 0 else i - 2
  9. i1 = x.shape[0] - 1 if i + 2 >= x.shape[0] else i + 2
  10. j0 = 0 if j - 2 < 0 else j - 2
  11. j1 = x.shape[1] - 1 if j + 2 >= x.shape[1] else j + 2
  12. annotation_text = f'{i},{j}: {x[sel.target.index]}\n5x5 average: {y[sel.target.index]:.2f}'
  13. sel.annotation.set_text(annotation_text)
  14. sel.annotation.get_bbox_patch().set(fc='gold', alpha=0.7)
  15. rect = Rectangle((j0 - 0.5, i0 - 0.5), j1 - j0 + 1, i1 - i0 + 1,
  16. linewidth=3, color='lime', alpha=0.3, clip_on=False)
  17. ax.add_artist(rect)
  18. sel.extras.append(rect)
  19. x = np.random.randint(10, size=(10, 15))
  20. y = convolve(x, np.ones((5, 5)), boundary='extend', preserve_nan=True)
  21. fig, ax = plt.subplots(figsize=(9, 3))
  22. img = ax.imshow(x, cmap='coolwarm', aspect='auto', alpha=0.8)
  23. ax.set_xticks(range(x.shape[1]))
  24. ax.set_yticks(range(x.shape[0]))
  25. fig.colorbar(img, ticks=range(10), ax=ax)
  26. for i in range(x.shape[0]):
  27. for j in range(x.shape[1]):
  28. ax.text(j, i, x[i, j], ha='center', va='center')
  29. cursor = mplcursors.cursor(img, hover=True)
  30. cursor.connect('add', show_rect)
  31. plt.show()

要创建xy的线性图,您可以使用np.ravel()将它们转换为1D:

  1. import matplotlib.pyplot as plt
  2. import numpy as np
  3. from astropy.convolution import convolve
  4. x = np.random.randint(10, size=(10, 10))
  5. y = convolve(x, np.ones((5, 5)), boundary='extend', preserve_nan=True)
  6. fig, ax = plt.subplots(figsize=(9, 3))
  7. ax.plot(np.arange(x.size), x.ravel(), color='dodgerblue', label='input values')
  8. ax.plot(np.arange(x.size), y.ravel(), color='crimson', label='convolution')
  9. ax.set_xticks(np.arange(x.size))
  10. ax.set_xticklabels([f'[{i},{j}]' for i in range(x.shape[0]) for j in range(x.shape[1])], rotation=90, size=8)
  11. ax.margins(x=0.02)
  12. ax.legend(bbox_to_anchor=[1.02, 1.02], loc='upper left')
  13. plt.tight_layout()
  14. plt.show()

展开查看全部

相关问题