【问题标题】:Matplotlib "ValueError: Image size of .... less than 2^16 in each direction" with log scaleMatplotlib "ValueError: Image size of .... less than 2^16 in each direction" with log scale
【发布时间】:2020-04-29 06:08:22
【问题描述】:

玩具问题:

import matplotlib.pyplot as plt

x = [10, 11, 12, 15]
y = [5, 7, 4, 3]
z = ["a", "b", "c", "d"]

fig, ax = plt.subplots(figsize = (6, 6))
ax.bar(x, y)

for i, j in enumerate(zip(y, z)):
    plt.text(i + 10, j[0] - 0.3, s = str(j[0]), color = 'white')
    plt.text(i + 10, j[0] + 0.1, s = str(j[1]), color = 'black')

plt.show()

这将创建一个图,将实际值作为文本标签,不错的东西。由于 x 值之间存在间隙,文本标签并未在每个条形上方对齐。

不用担心,可以插入一些数据:

import matplotlib.pyplot as plt

x = [10, 11, 12, 15]
y = [5, 7, 4, 3]
z = ["a", "b", "c", "d"]

x.insert(3, 13)
x.insert(4, 14)
y.insert(3, 0)
y.insert(4, 0)
z.insert(3, ' ')
z.insert(4, ' ')

fig, ax = plt.subplots(figsize = (6, 6))
ax.bar(x, y)
# ax.set_yscale('log')

for i, j in enumerate(zip(y, z)):
    plt.text(i + 10, j[0] - 0.3, s = str(j[0]), color = 'white')
    plt.text(i + 10, j[0] + 0.1, s = str(j[1]), color = 'black')

plt.show()

甜蜜,正是我们想要的,华丽的情节。

不过……

# ax.set_yscale('log')

如果 set_yscale('log') 未注释:

ValueError: Image size of 384x806494 pixels is too large. It must be less than 2^16 in each direction.

所以你不能在 y 值中有一个 0,因为 log 0 是未定义的。有道理。

除了现在,我无法解决原来的问题,因为 0 不能用于表示空条。

log 1 是 = 0,但是如果插入 1,仍然会显示一个 bar,因为我猜是什么原因?

matplotlib 版本“2.2.3”是否有任何解决方法? 0不能用,什么能用?

谢谢

【问题讨论】:

  • 这段代码在现代 matplotlib 上使用对数刻度可以正常工作。
  • @JodyKlymak 这实际上很令人沮丧 x) 我无法更新 VM 上需要执行类似代码的任何内容..
  • 你看使用barbottom参数了吗?

标签: python matplotlib plot bar-chart


【解决方案1】:

一种解决方法是在绘制之前记录您的 y 值并以线性比例绘制:

import matplotlib.pyplot as plt
import numpy as np

x = [10, 11, 12, 15]
y = [5, 7, 4, 3]
z = ["a", "b", "c", "d"]

x.insert(3, 13)
x.insert(4, 14)
y.insert(3, 0)
y.insert(4, 0)
z.insert(3, ' ')
z.insert(4, ' ')

fig, ax = plt.subplots(figsize = (6, 6))

mask = ~np.isinf(np.log(y)) # get mask of non-inf values
ax.bar(np.array(x)[mask], np.log(y)[mask]) # plot only non-inf values

for i, j in enumerate(zip(y, z)):
    if not j[0]: # skip 0 values
        continue

    plt.text(i + 10, np.log(j[0]) - 0.08, s=str(j[0]), color='white', ha='center')
    plt.text(i + 10, np.log(j[0]) + 0.02, s=str(j[1]), color='black', ha='center')

plt.show()

我不得不更改文本的 y 值以使其看起来不错。看看下面的结果:

【讨论】:

  • 我会添加 plt.text(..., ha="center") 以便文本和条形图共享同一个中心。
  • @Paddy Harrison 我喜欢你的解决方案。但我在运行它时遇到问题。这可能是因为我正在运行 python 2.7,但是当我运行您的代码时,我得到: ValueError: cannot convert float NaN to integer
  • 我在 Python2 中也遇到了同样的错误。我编辑了上面的答案以使其适用于 Python2。它涉及屏蔽inf 值并在绘制文本时跳过它们。我希望这会有所帮助。
  • 还添加了@Guimute 不错的建议。
  • @PaddyHarrison 美丽的回答伙伴,甚至不知道这是一件事。非常感谢:)
猜你喜欢
  • 2019-03-22
  • 2021-07-11
  • 1970-01-01
  • 1970-01-01
  • 2022-12-02
相关资源
最近更新 更多