matplotlib: метки центра x tick [duplicate]

24
задан Paymahn Moghadasian 22 November 2014 в 23:02
поделиться

2 ответа

Краткий ответ: вместо plt.hist(data, bins=range(50)) используйте plt.hist(data, bins=range(50)), чтобы получить выровненные по левому краю ячейки, plt.hist(data, bins=np.arange(50)-0.5), чтобы получить выровненные по центру бункеры и т. д.

Кроме того, если производительность имеет значение, потому что вы хотите подсчет уникальных целых чисел , есть несколько несколько более эффективных методов (np.bincount), которые я покажу в конце.

Заявление о проблемах


В качестве отдельного примера что вы видите, рассмотрите следующее:

import matplotlib.pyplot as plt
import numpy as np

# Generate a random array of integers between 0-9
# data.min() will be 0 and data.max() will be 9 (not 10)
data = np.random.randint(0, 10, 1000)

plt.hist(data, bins=10)
plt.xticks(range(10))
plt.show()

enter image description here [/g4]

Как вы заметили, бункеры не выровнены с целыми интервалами. Это в основном потому, что вы запросили 10 бункеров между 0 и 9, что не совсем то же самое, что просить бункеры для 10 уникальных значений.

Количество ящиков, которые вы want не совсем то же самое, что число уникальных значений. То, что вы на самом деле должны сделать в этом случае, - это вручную указать края бункера.

Чтобы объяснить, что происходит, давайте пропустим matplotlib.pyplot.hist и просто используем базовую функцию numpy.histogram.

Например, допустим, что у вас есть значения [0, 1, 2, 3]. Ваш первый инстинкт должен был бы сделать:

In [1]: import numpy as np

In [2]: np.histogram([0, 1, 2, 3], bins=4)
Out[2]: (array([1, 1, 1, 1]), array([ 0.  ,  0.75,  1.5 ,  2.25,  3.  ]))

Первый возвращаемый массив - это счетчики, а второй - края бункера (другими словами, где границы бара будут в вашем графике).

Обратите внимание, что мы получаем подсчеты, которые мы ожидали бы, но поскольку мы запросили 4 бункера между минимальными и максимальными данными, края бункера не имеют целочисленных значений.

Далее, вы можете попробовать:

In [3]: np.histogram([0, 1, 2, 3], bins=3)
Out[3]: (array([1, 1, 2]), array([ 0.,  1.,  2.,  3.]))

Обратите внимание, что края бина (второй массив) - это то, что вы ожидали, но подсчеты не совпадают. Это связано с тем, что последний бит ведет себя иначе, чем другие, как указано в документации для numpy.histogram:

Notes
-----
All but the last (righthand-most) bin is half-open.  In other words, if
`bins` is::

  [1, 2, 3, 4]

then the first bin is ``[1, 2)`` (including 1, but excluding 2) and the
second ``[2, 3)``.  The last bin, however, is ``[3, 4]``, which *includes*
4.

. Поэтому вам нужно точно указать, какие края вы хотите, и один за пределами вашей последней точки данных или сдвиньте края бункера на 0.5 интервалы. Например:

In [4]: np.histogram([0, 1, 2, 3], bins=range(5))
Out[4]: (array([1, 1, 1, 1]), array([0, 1, 2, 3, 4]))

Bin Alignment


Теперь применим это к первому примеру и посмотрим, как он выглядит:

import matplotlib.pyplot as plt
import numpy as np

# Generate a random array of integers between 0-9
# data.min() will be 0 and data.max() will be 9 (not 10)
data = np.random.randint(0, 10, 1000)

plt.hist(data, bins=range(11)) # <- The only difference
plt.xticks(range(10))
plt.show()

enter image description here [/g5]

Хорошо, отлично! Однако теперь у нас теперь есть выровненные слева вырезы. Что делать, если мы хотим, чтобы центральные вырезы были лучше отражены в том, что это уникальные значения?

Быстрый способ - просто сдвинуть края бункера:

import matplotlib.pyplot as plt
import numpy as np

# Generate a random array of integers between 0-9
# data.min() will be 0 and data.max() will be 9 (not 10)
data = np.random.randint(0, 10, 1000)

bins = np.arange(11) - 0.5
plt.hist(data, bins)
plt.xticks(range(10))
plt.xlim([-1, 10])

plt.show()

enter image description here [/g6]

Аналогично для выровненных справа бинов просто сдвиг на -1.

Другой подход


Для частного случая уникального Целочисленные значения, есть другой, более эффективный подход, который мы можем принять.

Если вы имеете дело с уникальными целыми числами, начиная с 0, вам лучше использовать numpy.bincount, чем использовать numpy.hist.

Например:

import matplotlib.pyplot as plt
import numpy as np

data = np.random.randint(0, 10, 1000)
counts = np.bincount(data)

# Switching to the OO-interface. You can do all of this with "plt" as well.
fig, ax = plt.subplots()
ax.bar(range(10), counts, width=1, align='center')
ax.set(xticks=range(10), xlim=[-1, 10])

plt.show()

enter image description here [/g7]

Для этого подхода есть два больших преимущества. Один - это скорость. numpy.histogram (и, следовательно, plt.hist) в основном управляет данными через numpy.digitize, а затем numpy.bincount. Поскольку вы имеете дело с уникальными целыми значениями, нет необходимости выполнять шаг numpy.digitize.

Однако большее преимущество - это больше контроля над дисплеем. Если вы предпочитаете более тонкие прямоугольники, используйте меньшую ширину:

import matplotlib.pyplot as plt
import numpy as np

data = np.random.randint(0, 10, 1000)
counts = np.bincount(data)

# Switching to the OO-interface. You can do all of this with "plt" as well.
fig, ax = plt.subplots()
ax.bar(range(10), counts, width=0.8, align='center')
ax.set(xticks=range(10), xlim=[-1, 10])

plt.show()

enter image description here [/g8]

65
ответ дан Joe Kington 20 August 2018 в 08:56
поделиться

Использование интерфейса OO для настройки тиков имеет преимущество центрирования меток при сохранении xticks. Кроме того, он работает с любой функцией построения графика и не зависит от np.bincount() или ax.bar()

import matplotlib.ticker as tkr
data = np.random.randint(0, 10, 1000)
mybins = range(11)
fig, ax = subplots()
ax.hist(data, bins=mybins, rwidth=0.8)
ax.set_xticks(mybins)
ax.xaxis.set_minor_locator(tkr.AutoMinorLocator(n=2))
ax.xaxis.set_minor_formatter(tkr.FixedFormatter(mybins))
ax.xaxis.set_major_formatter(tkr.NullFormatter())

for tick in ax.xaxis.get_minor_ticks():
    tick.tick1line.set_markersize(0)

result [/g0]

0
ответ дан IKavanagh 20 August 2018 в 08:56
поделиться
Другие вопросы по тегам:

Похожие вопросы: