Pyg*_*ion 14 python matplotlib
我想只绘制数组的一部分,修复x部分,但让y部分自动缩放.我尝试如下所示,但它不起作用.
有什么建议?
import numpy as np
import matplotlib.pyplot as plt
data=[np.arange(0,101,1),300-0.1*np.arange(0,101,1)]
plt.figure()
plt.scatter(data[0], data[1])
plt.xlim([50,100])
plt.autoscale(enable=True, axis='y')
plt.show()
Run Code Online (Sandbox Code Playgroud)
Dan*_*ein 17
虽然Joe Kington在建议只绘制必要的数据时肯定会提出最合理的答案,但在某些情况下最好绘制所有数据并缩放到某个部分.另外,拥有一个只需要轴对象的"autoscale_y"函数会很不错(也就是说,与此处的答案不同,这需要直接使用数据.)
这是一个只根据可见x区域中的数据重新缩放y轴的函数:
def autoscale_y(ax,margin=0.1):
"""This function rescales the y-axis based on the data that is visible given the current xlim of the axis.
ax -- a matplotlib axes object
margin -- the fraction of the total height of the y-data to pad the upper and lower ylims"""
import numpy as np
def get_bottom_top(line):
xd = line.get_xdata()
yd = line.get_ydata()
lo,hi = ax.get_xlim()
y_displayed = yd[((xd>lo) & (xd<hi))]
h = np.max(y_displayed) - np.min(y_displayed)
bot = np.min(y_displayed)-margin*h
top = np.max(y_displayed)+margin*h
return bot,top
lines = ax.get_lines()
bot,top = np.inf, -np.inf
for line in lines:
new_bot, new_top = get_bottom_top(line)
if new_bot < bot: bot = new_bot
if new_top > top: top = new_top
ax.set_ylim(bot,top)
Run Code Online (Sandbox Code Playgroud)
这是一种黑客攻击,并且在许多情况下可能不会起作用,但对于简单的情节,它可以很好地工作.
这是一个使用此函数的简单示例:
import numpy as np
import matplotlib.pyplot as plt
x = np.linspace(-100,100,1000)
y = x**2 + np.cos(x)*100
fig,axs = plt.subplots(1,2,figsize=(8,5))
for ax in axs:
ax.plot(x,y)
ax.plot(x,y*2)
ax.plot(x,y*10)
ax.set_xlim(-10,10)
autoscale_y(axs[1])
axs[0].set_title('Rescaled x-axis')
axs[1].set_title('Rescaled x-axis\nand used "autoscale_y"')
plt.show()
Run Code Online (Sandbox Code Playgroud)
自动缩放始终使用全范围的数据,因此y轴按y数据的完整范围缩放,而不仅仅是x限制内的范围.
如果您想显示数据的子集,那么仅绘制该子集可能最简单:
import numpy as np
import matplotlib.pyplot as plt
x, y = np.arange(0,101,1) ,300 - 0.1*np.arange(0,101,1)
mask = (x >= 50) & (x <= 100)
fig, ax = plt.subplots()
ax.scatter(x[mask], y[mask])
plt.show()
Run Code Online (Sandbox Code Playgroud)
我以 @DanHickstein 的答案为基础,涵盖了用于缩放 x 轴或 y 轴的绘图、散点图和 axhline/axvline 的情况。它可以被称为像autoscale()在最新的轴上工作一样简单。如果您想编辑它,请在 gist 上分叉它。
def autoscale(ax=None, axis='y', margin=0.1):
'''Autoscales the x or y axis of a given matplotlib ax object
to fit the margins set by manually limits of the other axis,
with margins in fraction of the width of the plot
Defaults to current axes object if not specified.
'''
import matplotlib.pyplot as plt
import numpy as np
if ax is None:
ax = plt.gca()
newlow, newhigh = np.inf, -np.inf
for artist in ax.collections + ax.lines:
x,y = get_xy(artist)
if axis == 'y':
setlim = ax.set_ylim
lim = ax.get_xlim()
fixed, dependent = x, y
else:
setlim = ax.set_xlim
lim = ax.get_ylim()
fixed, dependent = y, x
low, high = calculate_new_limit(fixed, dependent, lim)
newlow = low if low < newlow else newlow
newhigh = high if high > newhigh else newhigh
margin = margin*(newhigh - newlow)
setlim(newlow-margin, newhigh+margin)
def calculate_new_limit(fixed, dependent, limit):
'''Calculates the min/max of the dependent axis given
a fixed axis with limits
'''
if len(fixed) > 2:
mask = (fixed>limit[0]) & (fixed < limit[1])
window = dependent[mask]
low, high = window.min(), window.max()
else:
low = dependent[0]
high = dependent[-1]
if low == 0.0 and high == 1.0:
# This is a axhline in the autoscale direction
low = np.inf
high = -np.inf
return low, high
def get_xy(artist):
'''Gets the xy coordinates of a given artist
'''
if "Collection" in str(artist):
x, y = artist.get_offsets().T
elif "Line" in str(artist):
x, y = artist.get_xdata(), artist.get_ydata()
else:
raise ValueError("This type of object isn't implemented yet")
return x, y
Run Code Online (Sandbox Code Playgroud)
它和它的前身一样,有点 hacky,但这是必要的,因为集合和线有不同的返回 xy 坐标的方法,而且 axhline/axvline 很难使用,因为它只有两个数据点。
这是在行动中:
fig, axes = plt.subplots(ncols = 4, figsize=(12,3))
(ax1, ax2, ax3, ax4) = axes
x = np.linspace(0,100,300)
noise = np.random.normal(scale=0.1, size=x.shape)
y = 2*x + 3 + noise
for ax in axes:
ax.plot(x, y)
ax.scatter(x,y, color='red')
ax.axhline(50., ls='--', color='green')
for ax in axes[1:]:
ax.set_xlim(20,21)
ax.set_ylim(40,45)
autoscale(ax3, 'y', margin=0.1)
autoscale(ax4, 'x', margin=0.1)
ax1.set_title('Raw data')
ax2.set_title('Specificed limits')
ax3.set_title('Autoscale y')
ax4.set_title('Autoscale x')
plt.tight_layout()
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
24999 次 |
| 最近记录: |