我有以下代码,在网格上绘制一个函数,其中该函数恰好有一个非常大的整数值:
import matplotlib.pyplot as plt
from matplotlib.ticker import ScalarFormatter, FuncFormatter
p = 13
counts = [[0 for x in range(p)] for y in range(p)]
counts[0][0] = 1000000000
unique_counts = np.unique(counts)
plt.imshow(counts, cmap='viridis', origin='lower', extent=[0, p-1, 0, p-1])
cbar = plt.colorbar(ticks=unique_counts, format=ScalarFormatter(useOffset=False))
cbar.ax.yaxis.set_major_formatter(FuncFormatter(lambda x, _: format(int(x), ','))) # Format tick labels with commas
plt.show()
在 GoogleColab 中运行它,它运行得非常好,并且给出了漂亮的图
但是,如果我向上
counts[0][0] = 1000000000000000000000
说,那么我会收到以下错误:
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-12-0ec4c2551685> in <cell line: 8>()
6 counts[0][0] = 100000000000000000000
7 unique_counts = np.unique(counts)
----> 8 plt.imshow(counts, cmap='viridis', origin='lower', extent=[0, p-1, 0, p-1])
9 cbar = plt.colorbar(ticks=unique_counts, format=ScalarFormatter(useOffset=False))
10 cbar.ax.yaxis.set_major_formatter(FuncFormatter(lambda x, _: format(int(x), ','))) # Format tick labels with commas
3 frames
/usr/local/lib/python3.10/dist-packages/matplotlib/image.py in set_data(self, A)
699 if (self._A.dtype != np.uint8 and
700 not np.can_cast(self._A.dtype, float, "same_kind")):
--> 701 raise TypeError("Image data of dtype {} cannot be converted to "
702 "float".format(self._A.dtype))
703
TypeError: Image data of dtype object cannot be converted to float
我非常希望能够以精确的精度绘制采用非常大的整数值的函数(因此舍入/使用浮点数不会很好)。这可能吗?
Float 在处理大整数时存在问题。以下代码对我有用,我希望这是您想要的结果。 用科学记数法表示的可读数字总是比拥有极大的数字要好一些。
import matplotlib.pyplot as plt
from matplotlib.ticker import ScalarFormatter
import numpy as np
p = 13
counts = [[0 for x in range(p)] for y in range(p)]
counts[0][0] = 100000000000000000000000
# Convert counts to a NumPy array
counts_array = np.array(counts, dtype=float)
# Create the plot
plt.imshow(counts_array, cmap='viridis', origin='lower', extent=[0, p-1, 0, p-1])
cbar = plt.colorbar()
cbar.set_ticks([np.min(counts_array), np.max(counts_array)])
cbar.ax.yaxis.set_major_formatter(ScalarFormatter(useOffset=False, useMathText=True))
cbar.update_ticks()
plt.show()
我目前没有找到一种方法来精确地将大整数传递给
imshow()
,因为Matplotlib的内部工作原理依赖于Numpy数组来保存图像数据。如果您可以接受近似值,请使用
counts[0][0] = float(100000000000000000000)
您看到错误的原因是,保存图像数据的嵌套列表在显示之前由 Matplotlib 在内部转换为 Numpy 数组。这发生在
cbook.safe_masked_invalid()
,它被 _ImageBase._normalize_image_array()
调用,它被 _ImageBase.set_data()
调用,它被 Axes.imshow()
调用。
这里的问题链如下:
int_
数据类型表示的整数)默认会转换为 Numpy 的 object
数据类型。对于使用 counts[0][0] = 100000000000000000000
的数据会发生这种情况,但使用 counts[0][0] = 1000000000
时不会发生这种情况。您可以轻松检查相应的 Numpy 行为,如下所示:
np.array([100000000000000000000]).dtype
# >>> dtype('O') # Object data type
np.array([1000000000]).dtype
# >>> dtype('int64') # Integer data type
cbook.safe_masked_invalid()
。
_ImageBase._normalize_image_array()
检查数组的数据类型是否为int8
,或者是否可以转换为float
数据类型。这两种情况对于 Numpy 的 object
数据类型都是不可能的,因此会引发错误。
为了避免这一系列问题,我看到的唯一可能性是,一旦值变得太大,就将数据转换为浮点值或浮点数组,然后再将它们传递给
imshow()
。