Matplotlib - 固定x轴刻度和自动缩放y轴

时间:2015-04-05 19:59:02

标签: 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()

5 个答案:

答案 0 :(得分:15)

虽然Joe Kington当他建议只绘制必要的数据时,肯定会提出最明智的答案,但有些情况下最好绘制所有数据并缩放到某个部分。另外,有一个" autoscale_y"仅需要轴对象的函数(即,与答案here不同,这需要直接使用数据。)

这是一个根据可见x区域中的数据重新缩放y轴的函数:

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

这是一种黑客攻击,在许多情况下可能不会起作用,但对于一个简单的情节,它运作良好。

以下是使用此功能的简单示例:

{{1}}

enter image description here

答案 1 :(得分:6)

自动缩放始终使用全部数据,因此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()

答案 2 :(得分:1)

import numpy as np  # for the test data
import pandas as pd

# load the data into the dataframe; there are many ways to do this
df = pd.DataFrame({'x': np.arange(0,101,1), 'y': 300-0.1*np.arange(0,101,1)})

# select and plot the data
ax = df[df.x.between(50, 100)].plot(x='x', y='y', kind='scatter', figsize=(5, 4))

enter image description here

答案 3 :(得分:0)

我以@DanHickstein的答案为基础,以涵盖用于缩放x或y轴的绘图,散点图和axhline / axvline的情况。可以像在autoscale()上一样在最新的轴上工作。如果您要编辑它,请fork it on 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

像它的前一个一样,它有点笨拙,但这是必需的,因为集合和行具有不同的返回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()

autoscale in action

答案 4 :(得分:0)

我想补充@TomNorway的一个很好的答案(这节省了我很多时间),以处理某些艺术家完全由NaN组成的情况。

我所做的所有更改都在

内部
=sum(
  query(I10:I19,"select count(I) where I matches" & Regex!A1 & "label count(I) ''"),
  query(J10:J19,"select count(J) where J matches" & Regex!A1 & "label count(J) ''"),
  query(K10:K19,"select count(K) where K matches" & Regex!A1 & "label count(K) ''"),
  [etc. etc.]
)

干杯!

if len(fixed) > 2: