Как установить view_limits / диапазон оси в Matplotlib

#python-3.x #matplotlib

#python-3.x #matplotlib

Вопрос:

Мне нужно немного места до и после последнего расположения галочки на оси. Я бы просто использовал axis.set_xlim() , например, но это мешает моему (пользовательскому) локатору и перезапускает генерацию тиков. Я нашел и перезаписал view_limits() метод классов-локаторов, но они, похоже, не вызываются автоматически, а при вызове вручную они не оказывают никакого влияния на результирующий график. Я искал документы и источник, но не нашел решения. Я что-то упустил?

Для большей картины я хочу иметь локатор, который дает мне некоторое пространство до и после тиков и выбирает точки тиков, кратные «base», например, MultipleLocator, но автоматически масштабирует базу, если количество тиков превышает указанное значение. Если есть другой способ добиться этого без подкласса локатора, я весь внимание :).

Вот мой пример кода для подкласса locator с перезаписанным view_limits методом:

 import matplotlib.pyplot as plt
import numpy as np
from matplotlib.ticker import MaxNLocator

class MyLocator(MaxNLocator):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)

    def view_limits(self, dmin, dmax):
        bins = self.bin_boundaries(dmin, dmax)
        step = bins[1] - bins[0]
        result = np.array([bins[0] - step, bins[-1]   step])
        print(result)
        return result

a = 10.0
b = 99.0

t = np.arange(a, b, 0.1)
s = np.sin(0.1*np.pi*t)*np.exp(-t*0.01)

loc = MyLocator(9)

fig, ax = plt.subplots()
plt.plot(t, s)

ax.xaxis.set_major_locator(loc)
loc.autoscale()  # results in [   0.  110.] but doesnt change the plot
plt.show()
  

Ответ №1:

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

 import matplotlib.pyplot as plt
import numpy as np
from matplotlib.ticker import MaxNLocator

a = 10.0
b = 99.0

t = np.arange(a, b, 0.1)
s = np.sin(0.1*np.pi*t)*np.exp(-t*0.01)

loc = MaxNLocator(9)

fig, ax = plt.subplots()
plt.plot(t, s)

ax.xaxis.set_major_locator(loc)
ticks = ax.get_xticks()
newticks = np.zeros(len(ticks) 2)
newticks[0] = ticks[0]- (ticks[1]-ticks[0])
newticks[-1] = ticks[-1]  (ticks[1]-ticks[0])
newticks[1:-1] = ticks
ax.set_xticks(newticks)

plt.show()
  

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

1. спасибо за этот трюк! Я могу с этим работать. Я все же предпочел бы знать, почему весь view_limits-метод работает не так, как ожидалось.

Ответ №2:

Одно слегка хакерское решение, позволяющее избежать тиков вблизи краев графика, заключается в следующем:

 class PaddedMaxNLocator(mp.ticker.MaxNLocator):
    def __init__(self, *args, protected_width=0.25, **kwargs):
        # `prune` edge ticks that might now become visible
        super().__init__(*args, **kwargs, prune='both')
        # Clamp to some reasonable range
        self.protected_width = min(0.5, protected_width)

    def tick_values(self, vmin, vmax):
        diff = (vmax - vmin) * self.protected_width / 2
        return super().tick_values(vmin   diff, vmax - diff)