Matplotlib "ValueError: Размер изображения .... менее 2 ^ 16 в каждом направлении" с масштабом журнала - PullRequest
0 голосов
/ 29 апреля 2020

Игрушечная проблема:

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 есть пробел.

first plot

Не беспокойтесь, можете вставить некоторые данные:

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()

second plot

Сладкий, именно то, что мы хотели, великолепный сюжет.

Однако ...

# 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.

Таким образом, вы не можете иметь 0 в значениях y, потому что log 0 не определен. Имеет смысл.

За исключением случаев, я не могу исправить исходную проблему, поскольку 0 не может использоваться для представления пустого бара.

log 1 is = 0, но если вставить 1, по-прежнему отображается полоса, потому что, как мне кажется, причины?

Есть ли какие-либо обходные пути для этого с версией matplotlib '2.2.3'? Если 0 не может быть использовано, что может?

Спасибо

1 Ответ

1 голос
/ 29 апреля 2020

Обходной путь может заключаться в том, чтобы записать ваши значения 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 вашего текста, чтобы он выглядел хорошо. Посмотрите на результат ниже:

resulting plot

...