Как Matplotlib читает аргументы топоров - PullRequest
0 голосов
/ 09 сентября 2018

Я пришел из мира java и сейчас пытаюсь выучить python ради изучения matplotlib. Как программист Java, следующий фрагмент выглядел очень странно.

x = np.linspace(0, 2*np.pi, 400)
y = np.sin(x**2)

f, (ax1, ax2) = plt.subplots(1, 2, sharex='all', sharey='all')
ax1.plot(x, y)
ax1.set_title('Sharing Y axis')
ax2.scatter(x, y)

plt.show()

Мне было интересно, как plt.show () может читать конфигурации, заданные на осях, поскольку мы не передаем ему никаких аргументов. Может кто-нибудь объяснить грубую идею, как это поведение может быть достигнуто?

EDIT

Поскольку меня спрашивают @ImportanceOfBeingErnest, я вполне могу уточнить свое намерение. Мой вопрос не о том, как механика, которая пиплотирует создание изображения, мой вопрос больше о том, как конфигурация осей видна пиплоту. Джон Цвинк попытался в правильном направлении ответить на мой вопрос, я сам пришел к выводу, что это должно быть что-то, связанное с глобальным состоянием. Но, взглянув на внутреннюю реализацию подзаговоров, я не могу понять.

Давайте рассмотрим внутреннюю реализацию pyplot:

def subplots(nrows=1, ncols=1, sharex=False, sharey=False, squeeze=True,
             subplot_kw=None, gridspec_kw=None, **fig_kw):
    fig = figure(**fig_kw)
    axs = fig.subplots(nrows=nrows, ncols=ncols, sharex=sharex, sharey=sharey,
                       squeeze=squeeze, subplot_kw=subplot_kw,
                       gridspec_kw=gridspec_kw)
    return fig, axs

def subplots(self, nrows=1, ncols=1, sharex=False, sharey=False,
                 squeeze=True, subplot_kw=None, gridspec_kw=None):
            if isinstance(sharex, bool):
            sharex = "all" if sharex else "none"
        if isinstance(sharey, bool):
            sharey = "all" if sharey else "none"
        share_values = ["all", "row", "col", "none"]
        if sharex not in share_values:
            if isinstance(sharex, int):
                warnings.warn(
                    "sharex argument to subplots() was an integer. "
                    "Did you intend to use subplot() (without 's')?")

            raise ValueError("sharex [%s] must be one of %s" %
                             (sharex, share_values))
        if sharey not in share_values:
            raise ValueError("sharey [%s] must be one of %s" %
                             (sharey, share_values))
        if subplot_kw is None:
            subplot_kw = {}
        if gridspec_kw is None:
            gridspec_kw = {}

        if self.get_constrained_layout():
            gs = GridSpec(nrows, ncols, figure=self, **gridspec_kw)
        else:
            # this should turn constrained_layout off if we don't want it
            gs = GridSpec(nrows, ncols, figure=None, **gridspec_kw)

        # Create array to hold all axes.
        axarr = np.empty((nrows, ncols), dtype=object)
        for row in range(nrows):
            for col in range(ncols):
                shared_with = {"none": None, "all": axarr[0, 0],
                               "row": axarr[row, 0], "col": axarr[0, col]}
                subplot_kw["sharex"] = shared_with[sharex]
                subplot_kw["sharey"] = shared_with[sharey]
                axarr[row, col] = self.add_subplot(gs[row, col], **subplot_kw)

        # turn off redundant tick labeling
        if sharex in ["col", "all"]:
            # turn off all but the bottom row
            for ax in axarr[:-1, :].flat:
                ax.xaxis.set_tick_params(which='both',
                                         labelbottom=False, labeltop=False)
                ax.xaxis.offsetText.set_visible(False)
        if sharey in ["row", "all"]:
            # turn off all but the first column
            for ax in axarr[:, 1:].flat:
                ax.yaxis.set_tick_params(which='both',
                                         labelleft=False, labelright=False)
                ax.yaxis.offsetText.set_visible(False)

        if squeeze:
            # Discarding unneeded dimensions that equal 1.  If we only have one
            # subplot, just return it instead of a 1-element array.
            return axarr.item() if axarr.size == 1 else axarr.squeeze()
        else:
            # Returned axis array will be always 2-d, even if nrows=ncols=1.
            return axarr

Насколько я знаю, оси в этой строке создаются в виде массива numy

axarr = np.empty((nrows, ncols), dtype=object)

Но это локальная переменная, которая не указывает, как состояние осей, которые были изменены в основной программе, может быть видимым для pyplot. Это мой актуальный вопрос.

Ответы [ 2 ]

0 голосов
/ 09 сентября 2018

Прежде всего, строка fig = figure(**fig_kw) вызывает функцию pyplot.figure. Это регистрирует фигуру внутри конечного автомата pyplot.

fig является экземпляром matplotlib.figure.Figure. Далее вызывается метод subplots. По существу, это создаст массив и заполнит его matplotlib.axes.Axes экземплярами. Они созданы с self.add_subplot.

add_subplot инициализирует оси и сохраняет его как часть массива fig.axes фигуры.

Таким образом, в целом у вас есть pyplot, в котором хранятся цифры, а каждая фигура хранит в себе оси. При вызове plt.show() он в основном перебирает все цифры и показывает их. Для каждой фигуры будут нарисованы все оси внутри fig.axes. Если вы ранее манипулировали любой из осей, вызывая любой из их методов, они, конечно, будут приняты во внимание, потому что вы манипулировали именно тем объектом осей, который позже также рисуется.

0 голосов
/ 09 сентября 2018

Matplotlib's pyplot (это то, что вы импортировали как plt) - странная вещь с состоянием, предназначенная для эмуляции Matlab. Фактически это глобальная переменная (или оболочка для набора глобальных переменных, например, plt.gca() для «получения текущих осей»).

Многим людям проще в использовании, но это совершенно противоположно тому, что вы ожидаете от Java. Если вы предпочитаете, вполне возможно использовать Matplotlib без pyplot / plt, и в этом случае код, вероятно, будет выглядеть более привычным, чем исходный код из объектно-ориентированного программирования.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...