[英]Plotting a contour plot in Python with Matplotlib with data with imshow
[英]Python Matplotlib line plot aligned with contour/imshow
如何使用Python和Matplotlib將一個子圖的視覺寬度設置為等於另一個子圖的寬度? 第一個圖具有固定的寬高比和imshow的正方形像素。 然后我想在它下面放一個線條圖,但我不能這樣做並讓一切都對齊。
我很確定該解決方案涉及此轉換教程頁面上的信息。 我嘗試過使用fig.transFigure,ax.transAxes,ax.transData等,但還沒有成功。 我需要在上面板中找到軸的寬度和高度以及偏移,然后能夠在下面板中設置軸的寬度,高度和偏移。 不應包括軸標簽和刻度線等,也不應更改對齊方式。
例如,以下代碼
fig = plt.figure(1)
fig.clf()
data = np.random.random((3,3))
xaxis = np.arange(0,3)
yaxis = np.arange(0,3)
ax = fig.add_subplot(211)
ax.imshow(data, interpolation='none')
c = ax.contour(xaxis, yaxis, data, colors='k')
ax2 = fig.add_subplot(212)
matplotlib軸的輪廓由三件事控制:
fig.add_axes([left, bottom, width, height])
。軸限制(不計入刻度標簽)將始終在此框內。 adjustable
參數。 這可以是"datalim"
, "box"
或"box-forced"
。 (后者用於共享軸。) adjustable
)以保持指定的縱橫比。 縱橫比是指數據坐標, 而不是直接的軸的形狀。 對於最簡單的情況:
import numpy as np
import matplotlib.pyplot as plt
fig, axes = plt.subplots(nrows=2)
data = np.random.random((3,3))
xaxis = np.arange(0,3)
yaxis = np.arange(0,3)
axes[0].imshow(data, interpolation='none')
c = axes[0].contour(xaxis, yaxis, data, colors='k')
axes[1].set_aspect(1)
plt.show()
但是,如果您想確保它保持相同的形狀,並且您可以使用具有相同數據限制的兩個圖表,則可以執行以下操作:
import numpy as np
import matplotlib.pyplot as plt
fig, axes = plt.subplots(nrows=2), sharex=True, sharey=True)
plt.setp(axes.flat, adjustable='box-forced')
data = np.random.random((5,3))
xaxis = np.arange(0,3)
yaxis = np.arange(0,5)
axes[0].imshow(data, interpolation='none')
c = axes[0].contour(xaxis, yaxis, data, colors='k')
axes[1].plot([-0.5, 2.5], [-0.5, 4.5])
axes[1].set_aspect(1)
plt.show()
但是,您可能會注意到這看起來不太合適。 那是因為第二個子圖是由於我們繪制內容的順序而控制第一個子圖的范圍。
基本上,對於共享軸,我們最后繪制的內容將控制初始范圍,因此如果我們只是交換我們正在繪制的順序:
import numpy as np
import matplotlib.pyplot as plt
fig, axes = plt.subplots(nrows=2, sharex=True, sharey=True)
plt.setp(axes.flat, adjustable='box-forced')
data = np.random.random((5,3))
xaxis = np.arange(0,3)
yaxis = np.arange(0,5)
axes[1].plot([-0.5, 2.5], [-0.5, 4.5])
axes[1].set_aspect(1)
axes[0].imshow(data, interpolation='none')
c = axes[0].contour(xaxis, yaxis, data, colors='k')
plt.show()
當然,如果您不關心鏈接圖的交互式縮放/平移,您可以完全跳過共享軸,只需:
import numpy as np
import matplotlib.pyplot as plt
fig, axes = plt.subplots(nrows=2)
data = np.random.random((5,3))
xaxis = np.arange(0,3)
yaxis = np.arange(0,5)
axes[0].imshow(data, interpolation='none')
c = axes[0].contour(xaxis, yaxis, data, colors='k')
axes[1].plot([-0.5, 2.5], [-0.5, 4.5])
# Copy extents and aspect from the first axes...
axes[1].set_aspect(axes[0].get_aspect())
axes[1].axis(axes[0].axis())
plt.show()
如果您不希望兩個軸具有相同的數據范圍,則可以強制它們具有相同的大小(但如果以交互方式進行縮放,則不會鏈接它們)。 為此,您需要根據第二個圖的范圍和第一個圖的范圍/方面來計算第二個圖的寬高比。
import numpy as np
import matplotlib.pyplot as plt
fig, axes = plt.subplots(nrows=2)
data = np.random.random((3,3))
xaxis = np.arange(0,3)
yaxis = np.arange(0,3)
axes[0].imshow(data, interpolation='none')
c = axes[0].contour(xaxis, yaxis, data, colors='k')
axes[1].plot(np.linspace(0, 10, 100), np.random.normal(0, 1, 100).cumsum())
# Calculate the proper aspect for the second axes
aspect0 = axes[0].get_aspect()
if aspect0 == 'equal':
aspect0 = 1.0
dy = np.abs(np.diff(axes[1].get_ylim()))
dx = np.abs(np.diff(axes[1].get_xlim()))
aspect = aspect0 / (float(dy) / dx)
axes[1].set_aspect(aspect)
plt.show()
您是否在尋找相對於第一軸的任意定位? 你可以玩這個數字的bbox。
ax2.set_position(ax.get_position().translated(0, -.5))
將第二個軸放在第一個軸下,具有相同的基本形狀。 或者你可以做到
box = ax.get_position()
# Positioning code here
ax2.set_position(box)
您的定位代碼然后通過重新分配( box = box.translated(0, -.5)
)或變異( box.x1 += .1
)來改變框。 框似乎顯示了它的左下角和右上角,其屬性為.p0,.x0,.y0和.p1,.x1,.y1; 以及.width和.height
Box或多或少是一個圖形坐標,你也可以用原始數字“設置寬度,高度和偏移”: ax2.set_position([left, bottom, width, height])
PS:不幸的是,這個bbox還包括文本標簽的寬度和高度。 例如,你的第一個圖的寬度為0.27 ......高度為0.36 ......你不會通過改變尺寸來扭曲文本,但它確實意味着除非你從一個開始,否則很難得到一個完美的正方形。
在撰寫本文時,現有的兩個答案都很有用,但不提供解決方案。 隨后是解決方案。 此處使用的密鑰(不是其他答案)是直接訪問spine
位置。 在訪問坐標之前需要plt.draw()
來更新坐標。
import numpy as np
from matplotlib import pyplot as plt
im = np.arange(256).reshape(16,16)
fig = plt.figure(1)
fig.clf()
ax = fig.add_subplot(211)
ax.imshow(im)
plt.show()
transAxes = ax.transAxes
invFig = fig.transFigure.inverted()
llx,urx = plt.xlim()
lly,ury = plt.ylim()
llx0, lly0 = transAxes.transform((0,0))
llx1, lly1 = transAxes.transform((1,1))
plt.draw()
spleft = ax.spines['left'].get_verts()
spright = ax.spines['right'].get_verts()
llx0 = spleft[0,0]
llx1 = spright[0,0]
axp = invFig.transform(((lly0,llx0),(lly1,llx1)))
ax2 = fig.add_axes([axp[0,1],axp[0,0]-0.5,axp[1,1]-axp[0,1],axp[1,0]-axp[0,0]])
ax2.plot(np.arange(10))
plt.draw()
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.