Python / Matplotlib – Есть ли способ сделать разрывную ось?

Я пытаюсь создать сюжет с использованием pyplot с прерывистой осью x. Обычно это делается так, что ось будет иметь что-то вроде этого:

(значения) —- // —- (более поздние значения)

где // указывает, что вы пропускаете все значения (значения) и (более поздние значения).

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

4 Solutions collect form web for “Python / Matplotlib – Есть ли способ сделать разрывную ось?”

Ответ Павла – прекрасный способ сделать это.

Однако, если вы не хотите создавать настраиваемое преобразование, вы можете просто использовать два подзаголовка для создания такого же эффекта.

Вместо того, чтобы собрать пример с нуля, есть отличный пример этого, написанный Павлом Ивановым в примерах matplotlib (это только в текущем совете git, поскольку это было сделано только несколько месяцев назад. Это еще не на веб-странице). ,

Это просто простая модификация этого примера, чтобы иметь прерывистую ось x вместо оси y. (Вот почему я делаю этот пост CW)

В основном, вы просто делаете что-то вроде этого:

import matplotlib.pylab as plt import numpy as np # If you're not familiar with np.r_, don't worry too much about this. It's just # a series with points from 0 to 1 spaced at 0.1, and 9 to 10 with the same spacing. x = np.r_[0:1:0.1, 9:10:0.1] y = np.sin(x) fig,(ax,ax2) = plt.subplots(1, 2, sharey=True) # plot the same data on both axes ax.plot(x, y, 'bo') ax2.plot(x, y, 'bo') # zoom-in / limit the view to different portions of the data ax.set_xlim(0,1) # most of the data ax2.set_xlim(9,10) # outliers only # hide the spines between ax and ax2 ax.spines['right'].set_visible(False) ax2.spines['left'].set_visible(False) ax.yaxis.tick_left() ax.tick_params(labeltop='off') # don't put tick labels at the top ax2.yaxis.tick_right() # Make the spacing between the two axes a bit smaller plt.subplots_adjust(wspace=0.15) plt.show() 

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

Чтобы добавить поврежденные осенние линии // эффект, мы можем это сделать (опять же, модифицированный из примера Павла Иванова):

 import matplotlib.pylab as plt import numpy as np # If you're not familiar with np.r_, don't worry too much about this. It's just # a series with points from 0 to 1 spaced at 0.1, and 9 to 10 with the same spacing. x = np.r_[0:1:0.1, 9:10:0.1] y = np.sin(x) fig,(ax,ax2) = plt.subplots(1, 2, sharey=True) # plot the same data on both axes ax.plot(x, y, 'bo') ax2.plot(x, y, 'bo') # zoom-in / limit the view to different portions of the data ax.set_xlim(0,1) # most of the data ax2.set_xlim(9,10) # outliers only # hide the spines between ax and ax2 ax.spines['right'].set_visible(False) ax2.spines['left'].set_visible(False) ax.yaxis.tick_left() ax.tick_params(labeltop='off') # don't put tick labels at the top ax2.yaxis.tick_right() # Make the spacing between the two axes a bit smaller plt.subplots_adjust(wspace=0.15) # This looks pretty good, and was fairly painless, but you can get that # cut-out diagonal lines look with just a bit more work. The important # thing to know here is that in axes coordinates, which are always # between 0-1, spine endpoints are at these locations (0,0), (0,1), # (1,0), and (1,1). Thus, we just need to put the diagonals in the # appropriate corners of each of our axes, and so long as we use the # right transform and disable clipping. d = .015 # how big to make the diagonal lines in axes coordinates # arguments to pass plot, just so we don't keep repeating them kwargs = dict(transform=ax.transAxes, color='k', clip_on=False) ax.plot((1-d,1+d),(-d,+d), **kwargs) # top-left diagonal ax.plot((1-d,1+d),(1-d,1+d), **kwargs) # bottom-left diagonal kwargs.update(transform=ax2.transAxes) # switch to the bottom axes ax2.plot((-d,d),(-d,+d), **kwargs) # top-right diagonal ax2.plot((-d,d),(1-d,1+d), **kwargs) # bottom-right diagonal # What's cool about this is that now if we vary the distance between # ax and ax2 via f.subplots_adjust(hspace=...) or plt.subplot_tool(), # the diagonal lines will move accordingly, and stay right at the tips # of the spines they are 'breaking' plt.show() 

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

Я вижу много предложений по этой функции, но никаких указаний на то, что она была реализована. Это эффективное решение для времени. Он применяет преобразование ступенчатой ​​функции к оси x. Это много кода, но это довольно просто, так как большинство из них – это шаблонный пользовательский масштаб. Я не добавил графики, чтобы указать местоположение перерыва, так как это вопрос стиля. Удачи, закончив работу.

 from matplotlib import pyplot as plt from matplotlib import scale as mscale from matplotlib import transforms as mtransforms import numpy as np def CustomScaleFactory(l, u): class CustomScale(mscale.ScaleBase): name = 'custom' def __init__(self, axis, **kwargs): mscale.ScaleBase.__init__(self) self.thresh = None #thresh def get_transform(self): return self.CustomTransform(self.thresh) def set_default_locators_and_formatters(self, axis): pass class CustomTransform(mtransforms.Transform): input_dims = 1 output_dims = 1 is_separable = True lower = l upper = u def __init__(self, thresh): mtransforms.Transform.__init__(self) self.thresh = thresh def transform(self, a): aa = a.copy() aa[a>self.lower] = a[a>self.lower]-(self.upper-self.lower) aa[(a>self.lower)&(a<self.upper)] = self.lower return aa def inverted(self): return CustomScale.InvertedCustomTransform(self.thresh) class InvertedCustomTransform(mtransforms.Transform): input_dims = 1 output_dims = 1 is_separable = True lower = l upper = u def __init__(self, thresh): mtransforms.Transform.__init__(self) self.thresh = thresh def transform(self, a): aa = a.copy() aa[a>self.lower] = a[a>self.lower]+(self.upper-self.lower) return aa def inverted(self): return CustomScale.CustomTransform(self.thresh) return CustomScale mscale.register_scale(CustomScaleFactory(1.12, 8.88)) x = np.concatenate((np.linspace(0,1,10), np.linspace(9,10,10))) xticks = np.concatenate((np.linspace(0,1,6), np.linspace(9,10,6))) y = np.sin(x) plt.plot(x, y, '.') ax = plt.gca() ax.set_xscale('custom') ax.set_xticks(xticks) plt.show() 

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

Проверьте пакет с поврежденными пакетами:

 import matplotlib.pyplot as plt from brokenaxes import brokenaxes import numpy as np fig = plt.figure(figsize=(5,2)) bax = brokenaxes(xlims=((0, .1), (.4, .7)), ylims=((-1, .7), (.79, 1)), hspace=.05) x = np.linspace(0, 1, 100) bax.plot(x, np.sin(10 * x), label='sin') bax.plot(x, np.cos(10 * x), label='cos') bax.legend(loc=3) bax.set_xlabel('time') bax.set_ylabel('value') 

пример из обломков

Обращаясь к вопросу Фредерика Норда о том, как включить параллельную ориентацию диагональных «ломающихся» линий при использовании сетки с коэффициентами неравного 1: 1, могут быть полезны следующие изменения, основанные на предложениях Павла Иванова и Джо Кингтона. Коэффициент ширины можно варьировать с использованием переменных n и m.

 import matplotlib.pylab as plt import numpy as np import matplotlib.gridspec as gridspec x = np.r_[0:1:0.1, 9:10:0.1] y = np.sin(x) n = 5; m = 1; gs = gridspec.GridSpec(1,2, width_ratios = [n,m]) plt.figure(figsize=(10,8)) ax = plt.subplot(gs[0,0]) ax2 = plt.subplot(gs[0,1], sharey = ax) plt.setp(ax2.get_yticklabels(), visible=False) plt.subplots_adjust(wspace = 0.1) ax.plot(x, y, 'bo') ax2.plot(x, y, 'bo') ax.set_xlim(0,1) ax2.set_xlim(10,8) # hide the spines between ax and ax2 ax.spines['right'].set_visible(False) ax2.spines['left'].set_visible(False) ax.yaxis.tick_left() ax.tick_params(labeltop='off') # don't put tick labels at the top ax2.yaxis.tick_right() d = .015 # how big to make the diagonal lines in axes coordinates # arguments to pass plot, just so we don't keep repeating them kwargs = dict(transform=ax.transAxes, color='k', clip_on=False) on = (n+m)/n; om = (n+m)/m; ax.plot((1-d*on,1+d*on),(-d,d), **kwargs) # bottom-left diagonal ax.plot((1-d*on,1+d*on),(1-d,1+d), **kwargs) # top-left diagonal kwargs.update(transform=ax2.transAxes) # switch to the bottom axes ax2.plot((-d*om,d*om),(-d,d), **kwargs) # bottom-right diagonal ax2.plot((-d*om,d*om),(1-d,1+d), **kwargs) # top-right diagonal plt.show() 
  • Фиксированная ось y в графике Python в 12-часовом формате
  • Как я могу получить значения (x, y) линии, которые построены на графике контура?
  • Объект «module» не имеет атрибута «Gridspec», несмотря на вызов справки (gridspec), показывающий класс Gridspec
  • Matplotlib 3D plot - 2D-формат для ввода данных?
  • Фильтрация даты на оси x с помощью matplotlib Python
  • Imshow: степень и аспект
  • Matplotlib subplots_adjust hspace, чтобы заголовки и xlabels не перекрывались?
  • Проблема с цветовой палитрой Python 3d
  • Показывать не ascii (японский) персонажей в легенде сюжета панд
  • Matplotlib: Какова функция cmap в imshow?
  • Создание цветовой полосы для графика, сделанного с помощью plt.fill
  • Python - лучший язык программирования в мире.