散点图未正确调整 matplotlib 中的绘图范围
Scatter plot do not adjust properly plot range in matplotlib
我正在 matplotlib
版本 2.2.3 中使用 plt.plot
和 plt.scatter
绘制两个高斯分布(一个以 0 为中心,另一个以 100 为中心)。由于任何原因,对于 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, 'plot\n$\mu$ = 0 \n$\sigma$ = 1')
plt.subplot(2, 2, 2)
plt.scatter(center1, hist1)
plt.text(2, 0.27, 'scatter\n$\mu$ = 0 \n$\sigma$ = 1')
plt.subplot(2, 2, 3)
plt.plot(center2, hist2)
plt.text(127, 0.02, 'plot\n$\mu$ = 100 \n$\sigma$ = 15')
plt.subplot(2, 2, 4)
plt.scatter(center2, hist2)
plt.text(127, 0.02, 'scatter\n$\mu$ = 100 \n$\sigma$ = 15')
plt.show()
所以输出是:
如果有人可以提供帮助,我会很高兴,在此先感谢。如有任何答复或评论,我们将不胜感激。
集合的自动缩放(分散产生 PathCollection
)仍然是 unsolved problem,尽管正在讨论解决方法的想法。
在上面的示例中,一个奇怪的 hacky 解决方案是在创建散点之前向轴添加一个空图 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, 'plot\n$\mu$ = 0 \n$\sigma$ = 1')
plt.subplot(2, 2, 2)
plt.plot() ## <== empty plot
plt.scatter(center1, hist1)
plt.text(2, 0.27, 'scatter\n$\mu$ = 0 \n$\sigma$ = 1')
plt.subplot(2, 2, 3)
plt.plot(center2, hist2)
plt.text(127, 0.02, 'plot\n$\mu$ = 100 \n$\sigma$ = 15')
plt.subplot(2, 2, 4)
plt.plot() ## <== empty plot
plt.scatter(center2, hist2)
plt.text(127, 0.02, 'scatter\n$\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, 'plot\n$\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, 'scatter\n$\mu$ = 0 \n$\sigma$ = 1')
plt.subplot(2, 2, 3)
plt.plot(center2, hist2)
plt.text(127, 0.02, 'plot\n$\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, 'scatter\n$\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'scatter\n$\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()
好吧,老实说:我不知道。我唯一能发现的是,所描述的问题似乎始于最大值低于 0.1 的地块。 (即,只需尝试 plt.scatter(center1, hist1/10)
或 plt.scatter(center2, hist2*10)
)
但是,从你的例子来看,我在这里并不真正需要 scatter
。
如果您喜欢 plot
和蓝色圆圈的自动缩放 - 为什么不只是
plt.plot(center2, hist2, 'o')
...?
我正在 matplotlib
版本 2.2.3 中使用 plt.plot
和 plt.scatter
绘制两个高斯分布(一个以 0 为中心,另一个以 100 为中心)。由于任何原因,对于 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, 'plot\n$\mu$ = 0 \n$\sigma$ = 1')
plt.subplot(2, 2, 2)
plt.scatter(center1, hist1)
plt.text(2, 0.27, 'scatter\n$\mu$ = 0 \n$\sigma$ = 1')
plt.subplot(2, 2, 3)
plt.plot(center2, hist2)
plt.text(127, 0.02, 'plot\n$\mu$ = 100 \n$\sigma$ = 15')
plt.subplot(2, 2, 4)
plt.scatter(center2, hist2)
plt.text(127, 0.02, 'scatter\n$\mu$ = 100 \n$\sigma$ = 15')
plt.show()
所以输出是:
如果有人可以提供帮助,我会很高兴,在此先感谢。如有任何答复或评论,我们将不胜感激。
集合的自动缩放(分散产生 PathCollection
)仍然是 unsolved problem,尽管正在讨论解决方法的想法。
在上面的示例中,一个奇怪的 hacky 解决方案是在创建散点之前向轴添加一个空图 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, 'plot\n$\mu$ = 0 \n$\sigma$ = 1')
plt.subplot(2, 2, 2)
plt.plot() ## <== empty plot
plt.scatter(center1, hist1)
plt.text(2, 0.27, 'scatter\n$\mu$ = 0 \n$\sigma$ = 1')
plt.subplot(2, 2, 3)
plt.plot(center2, hist2)
plt.text(127, 0.02, 'plot\n$\mu$ = 100 \n$\sigma$ = 15')
plt.subplot(2, 2, 4)
plt.plot() ## <== empty plot
plt.scatter(center2, hist2)
plt.text(127, 0.02, 'scatter\n$\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, 'plot\n$\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, 'scatter\n$\mu$ = 0 \n$\sigma$ = 1')
plt.subplot(2, 2, 3)
plt.plot(center2, hist2)
plt.text(127, 0.02, 'plot\n$\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, 'scatter\n$\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'scatter\n$\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()
好吧,老实说:我不知道。我唯一能发现的是,所描述的问题似乎始于最大值低于 0.1 的地块。 (即,只需尝试 plt.scatter(center1, hist1/10)
或 plt.scatter(center2, hist2*10)
)
但是,从你的例子来看,我在这里并不真正需要 scatter
。
如果您喜欢 plot
和蓝色圆圈的自动缩放 - 为什么不只是
plt.plot(center2, hist2, 'o')
...?