메모
전체 예제 코드를 다운로드 하려면 여기 를 클릭 하십시오.
변환 자습서 #
다른 그래픽 패키지와 마찬가지로 Matplotlib는 변환 프레임워크 위에 구축되어 좌표계, 사용자 영역 데이터
좌표계, 축 좌표계, 그림 좌표계 및 디스플레이 좌표계 간에 쉽게 이동할 수 있습니다. 플로팅의 95%에서는 내부적으로 발생하므로 이에 대해 생각할 필요가 없지만 사용자 지정 그림 생성의 한계를 뛰어넘을 때 이러한 개체를 이해하면 기존 개체를 재사용할 수 있습니다. Matplotlib이 제공하는 변환을 사용하거나 직접 생성하십시오( 참조 matplotlib.transforms
). 아래 표에는 몇 가지 유용한 좌표계, 각 좌표계에 대한 설명, 각 좌표계에서 다음 위치로 이동하기 위한 변환 개체가 요약되어 있습니다.좌표를 표시 합니다. "변환 개체" 열에서 ax
는
Axes
인스턴스, fig
은
Figure
인스턴스 및 subfigure
는
SubFigure
인스턴스입니다.
좌표계 |
설명 |
시스템에서 디스플레이로 변환 객체 |
---|---|---|
"데이터" |
축에 있는 데이터의 좌표계입니다. |
|
"축" |
의 좌표계
|
|
"서브피규어" |
의 좌표계
|
|
"수치" |
의 좌표계
|
|
"숫자 인치" |
|
|
"x축", "y축" |
한 방향에서 데이터 좌표를 사용하고 다른 방향에서 축 좌표를 사용하는 혼합 좌표계. |
|
"표시하다" |
출력의 기본 좌표계 ; (0, 0)은 창의 왼쪽 하단이고 (너비, 높이)는 "표시 단위" 출력의 오른쪽 상단입니다. 단위의 정확한 해석은 백엔드에 따라 다릅니다. 예를 들어 Agg의 경우 픽셀이고 svg/pdf의 경우 포인트입니다. |
개체 는 Transform
원본 및 대상 좌표계에 순진하지만 위의 표에서 참조하는 개체는 해당 좌표계에서 입력을 받아 디스플레이 좌표계로 입력을 변환하도록 구성됩니다. 이것이 디스플레이
좌표계 None
에 "변환 개체" 열이 있는 이유입니다. 이미 디스플레이 좌표에 있습니다. 이름 지정 및 대상 규칙은 사용 가능한 "표준" 좌표계 및 변환을 추적하는 데 도움이 됩니다.
Transform.inverted
변환은 또한 출력 좌표계에서 다시 입력 좌표계로 변환을 생성하기 위해 (를 통해) 변환하는 방법을 알고
있습니다. 예를 들어 ax.transData
데이터 좌표의 값을 표시 좌표로 변환하고
표시 좌표에서 데이터 좌표 ax.transData.inversed()
로 matplotlib.transforms.Transform
이동합니다. 이는 일반적으로 디스플레이 공간에서 발생하는 사용자 인터페이스의 이벤트를 처리하고 데이터 좌표계에서 마우스 클릭 또는 키 누름이 발생한 위치를 알고 싶을 때 특히 유용합니다.
디스플레이 좌표 에서 아티스트의 위치를 지정 dpi
하면 그림의 또는 크기가 변경되면 상대 위치가 변경될 수 있습니다 . 개체가 위치와 크기를 변경할 수 있기 때문에 인쇄하거나 화면 해상도를 변경할 때 혼란을 일으킬 수 있습니다. 따라서 Axes 또는 Figure에 배치된 아티스트가 변형을 다른 것으로 설정하는 것이 가장 일반적입니다
IdentityTransform()
. 아티스트가 축에 추가될 때 기본값 은 데이터 좌표 에서 작업하고 생각 하고 Matplotlib가 표시add_artist
할 변환을 처리할 수 있도록 변환하는
것 입니다.ax.transData
데이터 좌표 #
가장 일반적으로 사용되는 좌표인 데이터 좌표계부터 시작하겠습니다. 좌표축에 데이터를 추가할 때마다 Matplotlib는 데이터 제한을 업데이트하며 가장 일반적으로 set_xlim()
및
set_ylim()
메서드로 업데이트됩니다. 예를 들어 아래 그림에서 데이터 제한은 x축에서 0에서 10까지, y축에서 -1에서 1까지 확장됩니다.
ax.transData
인스턴스를
사용하여 아래와 같이 데이터 에서 디스플레이 좌표계(단일 지점 또는 일련의 지점)로 변환할 수 있습니다.
In [14]: type(ax.transData)
Out[14]: <class 'matplotlib.transforms.CompositeGenericTransform'>
In [15]: ax.transData.transform((5, 0))
Out[15]: array([ 335.175, 247. ])
In [16]: ax.transData.transform([(5, 0), (1, 2)])
Out[16]:
array([[ 335.175, 247. ],
[ 132.435, 642.2 ]])
이 메서드를 사용하여 디스플레이 에서 데이터
좌표 로 이동 inverted()
하는 변환을 만들 수 있습니다 .
In [41]: inv = ax.transData.inverted()
In [42]: type(inv)
Out[42]: <class 'matplotlib.transforms.CompositeGenericTransform'>
In [43]: inv.transform((335.175, 247.))
Out[43]: array([ 5., 0.])
이 자습서와 함께 입력하는 경우 창 크기 또는 dpi 설정이 다른 경우 디스플레이 좌표의 정확한 값이 다를 수 있습니다. 마찬가지로 아래 그림에서 표시되는 points는 문서 그림 크기 기본값이 다르기 때문에 ipython 세션과 동일하지 않을 수 있습니다.
x = np.arange(0, 10, 0.005)
y = np.exp(-x/2.) * np.sin(2*np.pi*x)
fig, ax = plt.subplots()
ax.plot(x, y)
ax.set_xlim(0, 10)
ax.set_ylim(-1, 1)
xdata, ydata = 5, 0
# This computing the transform now, if anything
# (figure size, dpi, axes placement, data limits, scales..)
# changes re-calling transform will get a different value.
xdisplay, ydisplay = ax.transData.transform((xdata, ydata))
bbox = dict(boxstyle="round", fc="0.8")
arrowprops = dict(
arrowstyle="->",
connectionstyle="angle,angleA=0,angleB=90,rad=10")
offset = 72
ax.annotate('data = (%.1f, %.1f)' % (xdata, ydata),
(xdata, ydata), xytext=(-2*offset, offset), textcoords='offset points',
bbox=bbox, arrowprops=arrowprops)
disp = ax.annotate('display = (%.1f, %.1f)' % (xdisplay, ydisplay),
(xdisplay, ydisplay), xytext=(0.5*offset, -offset),
xycoords='figure pixels',
textcoords='offset points',
bbox=bbox, arrowprops=arrowprops)
plt.show()
경고
GUI 백엔드에서 위 예제의 소스 코드를 실행하면 데이터 및 디스플레이
주석에 대한 두 개의 화살표가 정확히 동일한 지점을 가리키지 않는 것을 확인할 수도 있습니다. Figure가 표시되기 전에 디스플레이 포인트가 계산되었고 GUI 백엔드가 Figure가 생성될 때 크기를 약간 조정할 수 있기 때문입니다. 그림의 크기를 직접 조정하면 효과가 더 두드러집니다. 이것은 디스플레이
공간 에서 거의 작업하지 않으려는 좋은 이유 중 하나 이지만 에 연결하여 그림 그리기에서 그림
좌표 'on_draw'
Event
를 업데이트 할 수 있습니다. 이벤트 처리 및 선택을 참조하십시오 .
축의 x 또는 y 제한을 변경하면 데이터 제한이 업데이트되어 변환이 새 표시점을 생성합니다. ylim만 변경하면 y-표시 좌표만 변경되고 xlim도 변경하면 둘 다 변경됩니다. 이에 대한 자세한 내용은 나중에
Bbox
.
In [54]: ax.transData.transform((5, 0))
Out[54]: array([ 335.175, 247. ])
In [55]: ax.set_ylim(-1, 2)
Out[55]: (-1, 2)
In [56]: ax.transData.transform((5, 0))
Out[56]: array([ 335.175 , 181.13333333])
In [57]: ax.set_xlim(10, 20)
Out[57]: (10, 20)
In [58]: ax.transData.transform((5, 0))
Out[58]: array([-171.675 , 181.13333333])
축 좌표 #
데이터 좌표계 다음으로 축은 아마도 두 번째로 가장 유용한 좌표계일 것입니다. 여기서 점 (0, 0)은 축 또는 서브플롯의 왼쪽 하단이고, (0.5, 0.5)는 중심이고, (1.0, 1.0)은 오른쪽 상단입니다. 범위 밖의 점을 참조할 수도 있으므로 (-0.1, 1.1)은 축 왼쪽 위입니다. 이 좌표계는 축에 텍스트를 배치할 때 매우 유용합니다. 예를 들어 축 창의 왼쪽 상단과 같은 고정된 위치에 텍스트 거품을 원하고 이동하거나 확대/축소할 때 해당 위치가 고정된 상태로 유지되는 경우가 많기 때문입니다. 다음은 4개의 패널을 만들고 저널에서 자주 볼 수 있는 'A', 'B', 'C', 'D' 레이블을 지정하는 간단한 예입니다.
fig = plt.figure()
for i, label in enumerate(('A', 'B', 'C', 'D')):
ax = fig.add_subplot(2, 2, i+1)
ax.text(0.05, 0.95, label, transform=ax.transAxes,
fontsize=16, fontweight='bold', va='top')
plt.show()
축 좌표계 에서 선이나 패치를 만들 수도 있지만 이것은 ax.transAxes
텍스트를 배치하는 데 사용하는 것보다 내 경험상 덜 유용합니다. Circle
그럼에도 불구하고 다음은 데이터 공간에 임의의 점을 표시 하고 축의 1/4 반지름으로 축 중앙에 반투명을 오버레이하는 어리석은 예입니다
. 축이 종횡비를 유지하지 않는 경우(참조 set_aspect()
) , 이것은 타원처럼 보일 것입니다. 팬/줌 도구를 사용하여 이동하거나 데이터 xlim 및 ylim을 수동으로 변경하면 데이터가 이동하는 것을 볼 수 있지만 원은 데이터
좌표에 있지 않고 항상 축 중심에 남아 있기 때문에 고정된 상태로 유지됩니다. .
fig, ax = plt.subplots()
x, y = 10*np.random.rand(2, 1000)
ax.plot(x, y, 'go', alpha=0.2) # plot some data in data coordinates
circ = mpatches.Circle((0.5, 0.5), 0.25, transform=ax.transAxes,
facecolor='blue', alpha=0.75)
ax.add_patch(circ)
plt.show()
혼합 변환 #
축 과 데이터 좌표를 혼합하는 혼합 좌표 공간 에서 그리는
것은 매우 유용합니다. 예를 들어 y 데이터의 일부 영역을 강조 표시하지만 데이터 제한, 팬 또는 확대/축소 수준 등에 관계없이 x축에 걸쳐 있는 수평 범위를 만드는 경우입니다. 사실 이러한 혼합된 선과 범위는 매우 유용하며 플롯하기 쉽게 만드는 기능이 내장되어 있지만(
,
,
,
참조 ) 교훈적인 목적으로 여기에서는 혼합 변환을 사용하여 수평 범위를 구현합니다. 이 트릭은 일반 데카르트 좌표계에서 볼 수 있는 것처럼 분리 가능한 변환에만 작동하지만
.axhline()
axvline()
axhspan()
axvspan()
PolarTransform
import matplotlib.transforms as transforms
fig, ax = plt.subplots()
x = np.random.randn(1000)
ax.hist(x, 30)
ax.set_title(r'$\sigma=1 \/ \dots \/ \sigma=2$', fontsize=16)
# the x coords of this transformation are data, and the y coord are axes
trans = transforms.blended_transform_factory(
ax.transData, ax.transAxes)
# highlight the 1..2 stddev region with a span.
# We want x to be in data coordinates and y to span from 0..1 in axes coords.
rect = mpatches.Rectangle((1, 0), width=1, height=1, transform=trans,
color='yellow', alpha=0.5)
ax.add_patch(rect)
plt.show()
메모
x가 데이터 좌표에 있고 y가 축
좌표에 있는 혼합 변환은 Matplotlib이 눈금, 눈금 레이블 등을 그리기 위해 내부적으로 사용하는 버전을 반환하는 도우미 메서드가 있으므로 매우 유용합니다. 메서드는 matplotlib.axes.Axes.get_xaxis_transform()
및
matplotlib.axes.Axes.get_yaxis_transform()
입니다. 따라서 위의 예에서 호출을 다음으로
blended_transform_factory()
바꿀 수 있습니다 get_xaxis_transform
.
trans = ax.get_xaxis_transform()
물리적 좌표로 플로팅하기 #
때때로 우리는 객체가 플롯에서 특정 물리적 크기가 되기를 원합니다. 여기서는 위와 동일한 원을 그리지만 물리적 좌표로 그립니다. 대화식으로 수행하는 경우 그림의 크기를 변경해도 왼쪽 하단 모서리에서 원의 오프셋이 변경되지 않고 크기가 변경되지 않으며 축의 종횡비에 관계없이 원이 원으로 남아 있음을 알 수 있습니다.
fig, ax = plt.subplots(figsize=(5, 4))
x, y = 10*np.random.rand(2, 1000)
ax.plot(x, y*10., 'go', alpha=0.2) # plot some data in data coordinates
# add a circle in fixed-coordinates
circ = mpatches.Circle((2.5, 2), 1.0, transform=fig.dpi_scale_trans,
facecolor='blue', alpha=0.75)
ax.add_patch(circ)
plt.show()
그림 크기를 변경해도 원의 절대 위치는 변경되지 않고 잘립니다.
fig, ax = plt.subplots(figsize=(7, 2))
x, y = 10*np.random.rand(2, 1000)
ax.plot(x, y*10., 'go', alpha=0.2) # plot some data in data coordinates
# add a circle in fixed-coordinates
circ = mpatches.Circle((2.5, 2), 1.0, transform=fig.dpi_scale_trans,
facecolor='blue', alpha=0.75)
ax.add_patch(circ)
plt.show()
또 다른 용도는 축의 데이터 포인트 주위에 설정된 물리적 치수로 패치를 배치하는 것입니다. 여기서 우리는 두 개의 변환을 함께 추가합니다. 첫 번째는 타원의 크기에 대한 배율을 설정하고 두 번째는 위치를 설정합니다. 그러면 타원이 원점에 배치되고 도우미 변환을 사용 하여 좌표계 ScaledTranslation
의 올바른 위치로 이동합니다 . ax.transData
이 도우미는 다음과 같이 인스턴스화됩니다.
trans = ScaledTranslation(xt, yt, scale_trans)
여기서 xt 및 yt 는 이동 오프셋이고 scale_trans 는 오프셋을 적용하기 전에 변환 시간에 xt 및 yt 를 스케일링하는 변환입니다 .
아래 변환에서 더하기 연산자의 사용에 유의하십시오. 이 코드는 다음과 같이 말합니다. 먼저 스케일 변환 fig.dpi_scale_trans
을 적용하여 타원을 적절한 크기로 만들고 여전히 (0, 0)에 중심을 둔 다음 데이터를 데이터 공간으로 변환 xdata[0]
합니다 ydata[0]
.
대화형 사용에서 타원은 확대/축소를 통해 축 제한이 변경되더라도 동일한 크기를 유지합니다.
fig, ax = plt.subplots()
xdata, ydata = (0.2, 0.7), (0.5, 0.5)
ax.plot(xdata, ydata, "o")
ax.set_xlim((0, 1))
trans = (fig.dpi_scale_trans +
transforms.ScaledTranslation(xdata[0], ydata[0], ax.transData))
# plot an ellipse around the point that is 150 x 130 points in diameter...
circle = mpatches.Ellipse((0, 0), 150/72, 130/72, angle=40,
fill=None, transform=trans)
ax.add_patch(circle)
plt.show()
메모
변환 순서가 중요합니다. 여기서 타원은 먼저 디스플레이 공간에서 올바른 치수를 지정한 다음 데이터 공간에서 올바른 지점으로 이동합니다. ScaledTranslation
첫 번째
작업을 수행한 경우 xdata[0]
및 ydata[0]
는 먼저 디스플레이 좌표( 200dpi 모니터에서)로 변환된 다음 해당 좌표는 타원의 중심을 화면 밖으로 밀어(예: ) 조정됩니다.[ 358.4 475.2]
fig.dpi_scale_trans
[ 71680. 95040.]
오프셋 변환을 사용하여 그림자 효과 만들기 #
의 또 다른 용도는 ScaledTranslation
다른 개체에 대해 약간 이동된 개체를 배치하는 것과 같이 다른 변환에서 오프셋된 새 변환을 만드는 것입니다.
일반적으로 이동 효과가 다른 확대/축소 수준 및 dpi 설정에서 일정하도록 데이터 좌표 가 아닌 포인트 또는 인치와 같은 일부 물리적 차원에서 이동을 원합니다 .
오프셋의 한 가지 용도는 그림자 효과를 만드는 것입니다. 첫 번째 객체와 동일한 객체 하나를 오른쪽과 바로 아래에 그리고 zorder를 조정하여 그림자를 먼저 그린 다음 객체를 그리는 것입니다. 그 위에 그림자.
여기서 우리 는 위의 사용과 반대 순서로
변환을 적용합니다 ScaledTranslation
. 플롯은 먼저 데이터 좌표( )에서 만든 다음 를 사용 하여 포인트 ax.transData
로 이동합니다
. (타이포그래피에서 포인트 는 1/72인치이며 오프셋을 포인트로 지정하면 저장된 dpi 해상도에 관계없이 그림이 동일하게 보입니다.)dx
dy
fig.dpi_scale_trans
fig, ax = plt.subplots()
# make a simple sine wave
x = np.arange(0., 2., 0.01)
y = np.sin(2*np.pi*x)
line, = ax.plot(x, y, lw=3, color='blue')
# shift the object over 2 points, and down 2 points
dx, dy = 2/72., -2/72.
offset = transforms.ScaledTranslation(dx, dy, fig.dpi_scale_trans)
shadow_transform = ax.transData + offset
# now plot the same data with our offset transform;
# use the zorder to make sure we are below the line
ax.plot(x, y, lw=3, color='gray',
transform=shadow_transform,
zorder=0.5*line.get_zorder())
ax.set_title('creating a shadow effect with an offset transform')
plt.show()
메모
matplotlib.transforms.offset_copy()
dpi 및 인치 오프셋은 오프셋이 추가된 새 변환을 반환하는 에서 생성하는 특수 도우미 함수가 있는 일반적인 사용 사례입니다 . 그래서 위에서 우리는 할 수 있었습니다:
shadow_transform = transforms.offset_copy(ax.transData,
fig=fig, dx, dy, units='inches')
변환 파이프라인 #
이 자습서에서 작업한 변환은 데이터 -> 표시ax.transData
에서 변환 파이프라인을 구성하는 세 가지 다른 변환의 합성입니다.
좌표. Michael Droettboom은 변환 프레임워크를 구현하여 이동 및 확대/축소할 때 발생하는 선형 아핀 변환에서 극좌표 및 로그 플롯에서 발생하는 비선형 프로젝션 및 스케일을 분리하는 깨끗한 API를 제공하도록 주의를 기울였습니다. 아핀 변환에 영향을 미치는 축을 이동하고 확대할 수 있기 때문에 효율성이 있지만 간단한 탐색 이벤트에서 잠재적으로 비용이 많이 드는 비선형 배율 또는 투영을 계산할 필요가 없을 수 있습니다. 아핀 변환 행렬을 함께 곱한 다음 한 번에 좌표에 적용하는 것도 가능합니다. 이것은 가능한 모든 변형에 해당되는 것은 아닙니다.
ax.transData
기본 분리 가능 축 Axes
클래스 에서 인스턴스가 정의되는 방법은 다음과 같습니다 .
self.transData = self.transScale + (self.transLimits + self.transAxes)
축의 (0, 0), (1, 1) 모서리를 매핑하거나 경계 상자를 표시 공간에 표시하는 Axes coordinatestransAxes
에서 위
의 인스턴스를 소개 했으므로 이 다른 두 부분을 살펴보겠습니다.
self.transLimits
데이터 에서 축 좌표 로 이동 하는 변환입니다
. 즉, 보기 xlim 및 ylim을 축의 단위 공간에 매핑 transAxes
한 다음 해당 단위 공간을 표시 공간으로 가져옵니다. 여기에서 작동하는 것을 볼 수 있습니다.
In [80]: ax = plt.subplot()
In [81]: ax.set_xlim(0, 10)
Out[81]: (0, 10)
In [82]: ax.set_ylim(-1, 1)
Out[82]: (-1, 1)
In [84]: ax.transLimits.transform((0, -1))
Out[84]: array([ 0., 0.])
In [85]: ax.transLimits.transform((10, -1))
Out[85]: array([ 1., 0.])
In [86]: ax.transLimits.transform((10, 1))
Out[86]: array([ 1., 1.])
In [87]: ax.transLimits.transform((5, 0))
Out[87]: array([ 0.5, 0.5])
그리고 우리는 이와 같은 반전 변환을 사용하여 단위 축 좌표에서 다시 데이터 좌표로 이동할 수 있습니다.
In [90]: inv.transform((0.25, 0.25))
Out[90]: array([ 2.5, -0.5])
마지막 조각은 self.transScale
데이터의 선택적 비선형 스케일링(예: 로그 축)을 담당하는 속성입니다. Axes가 처음 설정되면 기본 Matplotlib 축에 선형 스케일이 있기 때문에 항등 변환으로 설정되지만 와 같은 로그 스케일링 함수를 호출
semilogx()
하거나 명시적으로 스케일을 로그로 설정 set_xscale()
하면
ax.transScale
속성이 핸들로 설정됩니다. 비선형 투영. 스케일 변환은 각각 xaxis
및
yaxis
Axis
인스턴스의 속성입니다. 예를 들어 를 호출 ax.set_xscale('log')
하면 xaxis가 해당 배율을
matplotlib.scale.LogScale
인스턴스로 업데이트합니다.
분리할 수 없는 축인 PolarAxes의 경우 고려해야 할 부분이 하나 더 있는데 바로 투영 변환입니다. 는 transData
matplotlib.projections.polar.PolarAxes
일반적인 분리 가능한 matplotlib Axes와 유사하며 추가 조각이 하나 있습니다
transProjection
.
self.transData = self.transScale + self.transProjection + \
(self.transProjectionAffine + self.transAxes)
transProjection
지도 데이터의 위도와 경도 또는 극좌표 데이터의 반경과 세타와 같은 공간에서 분리 가능한 데카르트 좌표계로의 투영을 처리합니다. 패키지 에는 몇 가지 프로젝션 예제가 있으며 matplotlib.projections
자세한 내용을 알아보는 가장 좋은 방법은 해당 패키지의 소스를 열고 직접 만드는 방법을 확인하는 것입니다. Matplotlib는 확장 가능한 축과 프로젝션을 지원하기 때문입니다. Michael Droettboom은 해머 프로젝션 축을 만드는 좋은 튜토리얼 예제를 제공했습니다. 사용자 지정 프로젝션 을 참조하십시오
.
스크립트의 총 실행 시간: (0분 3.353초)