Точечный график неправильно настраивает диапазон графика в matplotlib

#python #matplotlib #scatter-plot #pad

#python #matplotlib #точечный график #панель

Вопрос:

Я строю два гауссиана (один с центром в 0, а другой в 100) с plt.plot и plt.scatter в matplotlib версии 2.2.3. По какой-либо причине вспомогательный график не регулирует диапазон графика автоматически для случая второй кривой на scatter графике.

Конечно, я могу сделать это вручную — в этом простом случае — но на самом деле у меня есть большая сетка, и я не хочу устанавливать диапазон один за другим.

Что это происходит? Есть ли какой-либо способ это исправить?

Это мой код:

 import numpy as np
import matplotlib.pyplot as plt

mu1, sigma1 = 0, 1
x1 = mu1   sigma1 * np.random.randn(10000)
hist1, bins1 = np.histogram(x1, bins='auto', density=True)
center1 = (bins1[:-1]   bins1[1:]) / 2

mu2, sigma2 = 100, 15
x2 = mu2   sigma2 * np.random.randn(10000)
hist2, bins2 = np.histogram(x2, bins='auto', density=True)
center2 = (bins2[:-1]   bins2[1:]) / 2

plt.subplot(2, 2, 1)
plt.plot(center1, hist1)
plt.text(2, 0.27, 'plotn$\mu$ = 0 n$\sigma$ = 1')
plt.subplot(2, 2, 2)
plt.scatter(center1, hist1)
plt.text(2, 0.27, 'scattern$\mu$ = 0 n$\sigma$ = 1')
plt.subplot(2, 2, 3)
plt.plot(center2, hist2)
plt.text(127, 0.02, 'plotn$\mu$ = 100 n$\sigma$ = 15')
plt.subplot(2, 2, 4)
plt.scatter(center2, hist2)
plt.text(127, 0.02, 'scattern$\mu$ = 100 n$\sigma$ = 15')

plt.show()
  

Таким образом, результат:
grid_gaussians

Я был бы рад, если бы кто-нибудь мог помочь с этим, заранее спасибо. Любой ответ или комментарий будут оценены.

Комментарии:

1. Насколько я помню, автоматическое масштабирование осей выполняется только для кривых, созданных plot , а не с помощью scatter . Я удивлен, что графики справа вообще масштабируются.

2. По крайней мере, я могу использовать такое же поведение в matplotlib 3.0.2, так что пока ошибка не исправлена…

Ответ №1:

Автоматическое масштабирование коллекций (scatter создает PathCollection ) по-прежнему остается нерешенной проблемой, хотя обсуждаются идеи для обходных путей.

Странное хакерское решение в случае приведенного выше примера заключается в добавлении пустого графика plt.plot() к осям перед созданием разброса.

 import numpy as np
import matplotlib.pyplot as plt

mu1, sigma1 = 0, 1
x1 = mu1   sigma1 * np.random.randn(10000)
hist1, bins1 = np.histogram(x1, bins='auto', density=True)
center1 = (bins1[:-1]   bins1[1:]) / 2

mu2, sigma2 = 100, 15
x2 = mu2   sigma2 * np.random.randn(10000)
hist2, bins2 = np.histogram(x2, bins='auto', density=True)
center2 = (bins2[:-1]   bins2[1:]) / 2


plt.subplot(2, 2, 1)
plt.plot(center1, hist1)
plt.text(2, 0.27, 'plotn$\mu$ = 0 n$\sigma$ = 1')
plt.subplot(2, 2, 2)
plt.plot()                      ## <== empty plot
plt.scatter(center1, hist1)
plt.text(2, 0.27, 'scattern$\mu$ = 0 n$\sigma$ = 1')
plt.subplot(2, 2, 3)
plt.plot(center2, hist2)
plt.text(127, 0.02, 'plotn$\mu$ = 100 n$\sigma$ = 15')
plt.subplot(2, 2, 4)
plt.plot()                      ## <== empty plot
plt.scatter(center2, hist2)
plt.text(127, 0.02, 'scattern$\mu$ = 100 n$\sigma$ = 15')

plt.show()
  

введите описание изображения здесь

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

 import numpy as np
import matplotlib.pyplot as plt

mu1, sigma1 = 0, 1
x1 = mu1   sigma1 * np.random.randn(10000)
hist1, bins1 = np.histogram(x1, bins='auto', density=True)
center1 = (bins1[:-1]   bins1[1:]) / 2

mu2, sigma2 = 100, 15
x2 = mu2   sigma2 * np.random.randn(10000)
hist2, bins2 = np.histogram(x2, bins='auto', density=True)
center2 = (bins2[:-1]   bins2[1:]) / 2


plt.subplot(2, 2, 1)
plt.plot(center1, hist1)
plt.text(2, 0.27, 'plotn$\mu$ = 0 n$\sigma$ = 1')
plt.subplot(2, 2, 2)
sentinel, = plt.plot(center1, hist1)            ## <== sentinel plot
sentinel.remove()
plt.scatter(center1, hist1)
plt.text(2, 0.27, 'scattern$\mu$ = 0 n$\sigma$ = 1')
plt.subplot(2, 2, 3)
plt.plot(center2, hist2)
plt.text(127, 0.02, 'plotn$\mu$ = 100 n$\sigma$ = 15')
plt.subplot(2, 2, 4)
sentinel, = plt.plot(center2, hist2)            ## <== sentinel plot
sentinel.remove()
plt.scatter(center2, hist2)
plt.text(127, 0.02, 'scattern$\mu$ = 100 n$\sigma$ = 15')


plt.show()
  

введите описание изображения здесь

Наконец, учтите, что в случае большой сетки графиков вам в настоящее время необходимо отрегулировать положение текста вручную в любом случае. Таким образом, реальным решением здесь было бы создать функцию, которая вызывается для каждой оси, и позволить ей делать все автоматически.

 import numpy as np
import matplotlib.pyplot as plt
from matplotlib.offsetbox import AnchoredText

def plot_my_hist(mu, sigma, ax=None):
    ax = ax or plt.gca()
    x = mu   sigma * np.random.randn(10000)
    hist, bins = np.histogram(x, bins='auto', density=True)
    center = (bins[:-1]   bins[1:]) / 2
    # Plot
    sentinel, = ax.plot(center, hist)      ## <== sentinel plot
    sentinel.remove()
    ax.scatter(center, hist)
    # Annotation
    at = AnchoredText(f'scattern$\mu$ = {mu} n$\sigma$ = {sigma}',
                      loc='upper right')
    ax.add_artist(at)

mus = [0, 0, 12, 12, 100, 100]
sigmas = [1, 15, 1, 15, 1, 15]
fig, axes = plt.subplots(ncols=3, nrows=2, figsize=(10,6))

for ax, mu, sigma in zip(axes.T.flat, mus, sigmas):
    plot_my_hist(mu, sigma, ax=ax)


fig.tight_layout()
plt.show()
  

введите описание изображения здесь

Ответ №2:

Хорошо, честно говоря: я понятия не имею. Единственное, что я смог выяснить, это то, что описанная проблема, похоже, начинается для графиков с максимальными значениями ниже 0.1. (Т. Е. просто попробуйте plt.scatter(center1, hist1/10) или plt.scatter(center2, hist2*10) )

Однако из вашего примера я действительно не понимаю, что scatter здесь нужно.
Если вам нравится автоматическое масштабирование plot , а также синие круги — почему бы просто

 plt.plot(center2, hist2, 'o')
  

…?

Комментарии:

1. Если вас интересует основная проблема, проверьте ссылку в моем ответе. Предложенное здесь решение, вероятно, подходит для рассматриваемой проблемы, где не требуются разные цвета или размеры.

2. @ImportanceOfBeingErnest верно, в mcve, вероятно, может отсутствовать подробная информация о реальной программе, которая, очевидно, потребуется scatter .