Matplotlib 애플리케이션 인터페이스(API) #

Matplotlib에는 두 가지 주요 애플리케이션 인터페이스 또는 라이브러리 사용 스타일이 있습니다.

  • Figure 또는 Axes 개체의 메서드를 사용하여 다른 아티스트를 생성하고 단계별로 시각화를 구축하는 명시적인 "Axes" 인터페이스입니다. 이것은 "객체 지향" 인터페이스라고도 합니다.

  • 마지막으로 생성된 Figure 및 Axes를 추적하고 사용자가 원하는 개체에 아티스트를 추가하는 암시적 "pyplot" 인터페이스입니다.

또한 여러 다운스트림 라이브러리( pandasxarray 와 같은 )는 plot사용자가 를 호출할 수 있도록 데이터 클래스에 직접 구현된 메서드를 제공합니다 data.plot().

이러한 인터페이스 간의 차이점은 약간 혼란스러울 수 있습니다. 특히 웹에서 둘 중 하나를 사용하는 스니펫 또는 동일한 예에서 여러 인터페이스를 사용하는 경우가 있습니다. 여기서 우리는 사용자가 라이브러리를 더 잘 탐색할 수 있도록 "pyplot" 및 다운스트림 인터페이스가 명시적 "Axes" 인터페이스와 어떻게 관련되는지 지적하려고 시도합니다.

기본 Matplotlib 인터페이스 #

명시적인 "Axes" 인터페이스 #

"Axes" 인터페이스는 Matplotlib이 구현되는 방식이며 많은 사용자 지정 및 미세 조정이 이 수준에서 수행됩니다.

이 인터페이스는 Figure클래스의 인스턴스를 인스턴스화하고( fig아래) 해당 객체에 메서드 subplots메서드(또는 유사)를 사용하여 하나 이상의 Axes객체를 만든 다음( ax아래) Axes에서 그리기 메서드를 호출하여 작동합니다( plot이 예에서는).

import matplotlib.pyplot as plt

fig = plt.figure()
ax = fig.subplots()
ax.plot([1, 2, 3, 4], [0, 0.5, 1, 0.2])

( 소스 코드 , png )

../../_images/api_interfaces-1.png

각 개체가 명시적으로 참조되고 다음 개체를 만드는 데 사용되기 때문에 이를 "명시적" 인터페이스라고 합니다. 개체에 대한 참조를 유지하는 것은 매우 유연하며 개체가 생성된 후 표시되기 전에 개체를 사용자 지정할 수 있습니다.

암시적 "pyplot" 인터페이스 #

pyplot모듈은 대부분의 플로팅 Axes방법을 숨김으로써 사용자를 위해 Figure 및 Axes 생성이 수행되는 위와 동등한 것을 제공합니다.

import matplotlib.pyplot as plt

plt.plot([1, 2, 3, 4], [0, 0.5, 1, 0.2])

( 소스 코드 , png )

../../_images/api_interfaces-2.png

이는 특히 대화형 작업이나 간단한 스크립트를 수행할 때 편리할 수 있습니다. 현재 그림에 대한 참조는 를 사용하여 검색할 수 있고 gcf현재 축에 대한 참조는 를 통해 검색할 수 있습니다 gca. 모듈 은 pyplot그림 목록을 유지하고 각 그림은 다음과 같이 사용자를 위해 그림의 축 목록을 유지합니다.

import matplotlib.pyplot as plt

plt.subplot(1, 2, 1)
plt.plot([1, 2, 3], [0, 0.5, 0.2])

plt.subplot(1, 2, 2)
plt.plot([3, 2, 1], [0, 0.5, 0.2])

( 소스 코드 , png )

../../_images/api_interfaces-3.png

다음과 같습니다.

import matplotlib.pyplot as plt

plt.subplot(1, 2, 1)
ax = plt.gca()
ax.plot([1, 2, 3], [0, 0.5, 0.2])

plt.subplot(1, 2, 2)
ax = plt.gca()
ax.plot([3, 2, 1], [0, 0.5, 0.2])

( 소스 코드 , png )

../../_images/api_interfaces-4.png

명시적 인터페이스에서 이것은 다음과 같습니다.

import matplotlib.pyplot as plt

fig, axs = plt.subplots(1, 2)
axs[0].plot([1, 2, 3], [0, 0.5, 0.2])
axs[1].plot([3, 2, 1], [0, 0.5, 0.2])

( 소스 코드 , png )

../../_images/api_interfaces-5.png

왜 명시적입니까? #

에서 참조하지 않는 이전 축에서 역추적하고 작업을 수행해야 하는 경우 어떻게 됩니까 plt.gca()? 한 가지 간단한 방법은 subplot동일한 인수를 사용하여 다시 호출하는 것입니다. 그러나 그것은 곧 우아하지 않게 됩니다. Figure 개체를 검사하고 Axes 개체 목록을 가져올 수도 있지만 이는 오해의 소지가 있습니다(컬러바도 Axes입니다!). 가장 좋은 해결책은 생성한 모든 Axes에 대한 핸들을 저장하는 것일 것입니다. 하지만 그렇게 한다면 처음에 모든 Axes 객체를 생성하지 않는 이유는 무엇입니까?

첫 번째 접근 방식은 다시 호출하는 것입니다 plt.subplot.

import matplotlib.pyplot as plt

plt.subplot(1, 2, 1)
plt.plot([1, 2, 3], [0, 0.5, 0.2])

plt.subplot(1, 2, 2)
plt.plot([3, 2, 1], [0, 0.5, 0.2])

plt.suptitle('Implicit Interface: re-call subplot')

for i in range(1, 3):
    plt.subplot(1, 2, i)
    plt.xlabel('Boo')

( 소스 코드 , png )

../../_images/api_interfaces-6.png

두 번째는 핸들을 저장하는 것입니다.

import matplotlib.pyplot as plt

axs = []
ax = plt.subplot(1, 2, 1)
axs += [ax]
plt.plot([1, 2, 3], [0, 0.5, 0.2])

ax = plt.subplot(1, 2, 2)
axs += [ax]
plt.plot([3, 2, 1], [0, 0.5, 0.2])

plt.suptitle('Implicit Interface: save handles')

for i in range(2):
    plt.sca(axs[i])
    plt.xlabel('Boo')

( 소스 코드 , png )

../../_images/api_interfaces-7.png

그러나 권장되는 방법은 처음부터 명시적으로 지정하는 것입니다.

import matplotlib.pyplot as plt

fig, axs = plt.subplots(1, 2)
axs[0].plot([1, 2, 3], [0, 0.5, 0.2])
axs[1].plot([3, 2, 1], [0, 0.5, 0.2])
fig.suptitle('Explicit Interface')
for i in range(2):
    axs[i].set_xlabel('Boo')

( 소스 코드 , png )

../../_images/api_interfaces-8.png

타사 라이브러리 "데이터 개체" 인터페이스 #

일부 타사 라이브러리는 데이터 개체에 대한 플로팅을 구현하도록 선택했습니다. 예를 들어 , xarray 및 기타 타사 라이브러리 data.plot()에서 볼 수 있습니다. 설명을 위해 다운스트림 라이브러리는 데이터가 함께 저장된 간단한 데이터 컨테이너를 구현한 다음 메서드 를 구현할 수 있습니다.pandasxyplot

import matplotlib.pyplot as plt

# supplied by downstream library:
class DataContainer:

    def __init__(self, x, y):
        """
        Proper docstring here!
        """
        self._x = x
        self._y = y

    def plot(self, ax=None, **kwargs):
        if ax is None:
            ax = plt.gca()
        ax.plot(self._x, self._y, **kwargs)
        ax.set_title('Plotted from DataClass!')
        return ax


# what the user usually calls:
data = DataContainer([0, 1, 2, 3], [0, 0.2, 0.5, 0.3])
data.plot()

( 소스 코드 , png )

../../_images/api_interfaces-9.png

따라서 라이브러리는 사용자에게 모든 핵심 정보를 숨길 수 있으며 종종 좋은 레이블, 색상 맵 선택 및 기타 편리한 기능을 사용하여 데이터 유형에 적합한 시각화를 만들 수 있습니다.

그러나 위의 경우 라이브러리에서 제공한 제목이 마음에 들지 않았을 수 있습니다. 고맙게도 메서드에서 Axes를 다시 전달 plot()하고 명시적인 Axes 인터페이스를 이해하면 다음을 호출 하여 제목을 사용자 지정할 수 있습니다.ax.set_title('My preferred title')

또한 많은 라이브러리에서 plot메소드가 선택적 ax 인수를 허용하도록 허용합니다. 이를 통해 우리가 배치하고 아마도 사용자 정의한 축에 시각화를 배치할 수 있습니다.

요약 #

전반적으로 명시적 "Axes" 인터페이스는 가장 유연하고 다른 인터페이스의 기반이 되므로 이해하는 것이 유용합니다. 사용자는 일반적으로 명시적 인터페이스로 드롭다운하고 기본 개체에서 작동하는 방법을 알아낼 수 있습니다. 명시적 인터페이스는 설정하기가 좀 더 장황할 수 있지만 복잡한 플롯은 종종 암시적 "pyplot" 인터페이스를 사용하려고 시도하는 것보다 간단해집니다.

메모

pyplot우리가 두 인터페이스 모두에 대해 가져오는 것이 사람들에게 때때로 혼란스럽습니다 . 현재 이 pyplot모듈은 "pyplot" 인터페이스를 구현하지만 최상위 수준의 Figure 및 Axes 생성 방법도 제공하고 궁극적으로 그래픽 사용자 인터페이스가 사용되는 경우 스핀업합니다. 따라서 pyplot선택한 인터페이스에 관계없이 여전히 필요합니다.

마찬가지로 파트너 라이브러리에서 제공하는 선언적 인터페이스는 "Axes" 인터페이스에서 액세스할 수 있는 개체를 사용하고 종종 이를 인수로 받아들이거나 메서드에서 다시 전달합니다. 일반적으로 명시적 "Axes" 인터페이스를 사용하여 기본 시각화의 사용자 지정을 수행하거나 데이터를 NumPy 배열로 압축을 풀고 Matplotlib에 직접 전달하는 것이 필수적입니다.

부록: 데이터 구조가 있는 "Axes" 인터페이스 #

대부분의 메서드는 메서드에 데이터 개체를 전달하고 인수를 문자열로 지정하여 Axes또 다른 API 주소 지정을 허용합니다 .

import matplotlib.pyplot as plt

data = {'xdat': [0, 1, 2, 3], 'ydat': [0, 0.2, 0.4, 0.1]}
fig, ax = plt.subplots(figsize=(2, 2))
ax.plot('xdat', 'ydat', data=data)

( 소스 코드 , png )

../../_images/api_interfaces-10.png

부록: "pylab" 인터페이스 #

권장하지 않는 또 다른 인터페이스가 하나 더 있는데, 그것은 기본적으로 . 이를 통해 사용자는 간단히 . 편리하긴 하지만 사용자가 무의식적으로 변수 이름을 pyplot 메서드와 같은 이름으로 지정하면 명백한 문제가 발생할 수 있습니다.from matplotlib.pyplot import *plot(x, y)