Python 将两个热图合二为一的包(将每个正方形分成两个三角形)
Python package to plot two heatmaps in one (split each square into two triangles)
我一直在搜索,但找不到通过将热图中的每个正方形分成两个三角形(类似于我在论文中看到的附图)在一个图形中绘制两个热图的简单解决方案。有人知道可以做到这一点的 Python 软件包吗?我试过 seaborn,但我不认为它有一个简单的方法来实现这一点。
感谢您的宝贵时间!
-彼得
plt.tripcolor
为三角形网格着色类似于 plt.pcolormesh
为矩形网格着色。同样类似于pcolormesh
,需要注意的是顶点的行数和列数少于三角形的数目。此外,需要将数组制成一维 (np.ravel
)。所有这些重新编号为 1D 可能有点棘手。
例如,下面的代码根据 x*y mod 10
创建一个着色,并为上三角和下三角使用两个不同的颜色图。
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.tri import Triangulation
M = 30
N = 20
x = np.arange(M + 1)
y = np.arange(N + 1)
xs, ys = np.meshgrid(x, y)
zs = (xs * ys) % 10
zs = zs[:-1, :-1].ravel()
triangles1 = [(i + j*(M+1), i+1 + j*(M+1), i + (j+1)*(M+1)) for j in range(N) for i in range(M)]
triangles2 = [(i+1 + j*(M+1), i+1 + (j+1)*(M+1), i + (j+1)*(M+1)) for j in range(N) for i in range(M)]
triang1 = Triangulation(xs.ravel(), ys.ravel(), triangles1)
triang2 = Triangulation(xs.ravel(), ys.ravel(), triangles2)
img1 = plt.tripcolor(triang1, zs, cmap=plt.get_cmap('inferno', 10), vmax=10)
img2 = plt.tripcolor(triang2, zs, cmap=plt.get_cmap('viridis', 10), vmax=10)
plt.colorbar(img2, ticks=range(10), pad=-0.05)
plt.colorbar(img1, ticks=range(10))
plt.xlim(x[0], x[-1])
plt.ylim(y[0], y[-1])
plt.xticks(x, rotation=90)
plt.yticks(y)
plt.show()
PS:为了让整数在单元格的中心(而不是在它们的边界)很好地刻度,需要进行以下更改:
triang1 = Triangulation(xs.ravel()-0.5, ys.ravel()-0.5, triangles1)
triang2 = Triangulation(xs.ravel()-0.5, ys.ravel()-0.5, triangles2)
# ...
plt.xlim(x[0]-0.5, x[-1]-0.5)
plt.ylim(y[0]-0.5, y[-1]-0.5)
plt.xticks(x[:-1], rotation=90)
plt.yticks(y[:-1])
我一直在搜索,但找不到通过将热图中的每个正方形分成两个三角形(类似于我在论文中看到的附图)在一个图形中绘制两个热图的简单解决方案。有人知道可以做到这一点的 Python 软件包吗?我试过 seaborn,但我不认为它有一个简单的方法来实现这一点。
感谢您的宝贵时间!
-彼得
plt.tripcolor
为三角形网格着色类似于 plt.pcolormesh
为矩形网格着色。同样类似于pcolormesh
,需要注意的是顶点的行数和列数少于三角形的数目。此外,需要将数组制成一维 (np.ravel
)。所有这些重新编号为 1D 可能有点棘手。
例如,下面的代码根据 x*y mod 10
创建一个着色,并为上三角和下三角使用两个不同的颜色图。
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.tri import Triangulation
M = 30
N = 20
x = np.arange(M + 1)
y = np.arange(N + 1)
xs, ys = np.meshgrid(x, y)
zs = (xs * ys) % 10
zs = zs[:-1, :-1].ravel()
triangles1 = [(i + j*(M+1), i+1 + j*(M+1), i + (j+1)*(M+1)) for j in range(N) for i in range(M)]
triangles2 = [(i+1 + j*(M+1), i+1 + (j+1)*(M+1), i + (j+1)*(M+1)) for j in range(N) for i in range(M)]
triang1 = Triangulation(xs.ravel(), ys.ravel(), triangles1)
triang2 = Triangulation(xs.ravel(), ys.ravel(), triangles2)
img1 = plt.tripcolor(triang1, zs, cmap=plt.get_cmap('inferno', 10), vmax=10)
img2 = plt.tripcolor(triang2, zs, cmap=plt.get_cmap('viridis', 10), vmax=10)
plt.colorbar(img2, ticks=range(10), pad=-0.05)
plt.colorbar(img1, ticks=range(10))
plt.xlim(x[0], x[-1])
plt.ylim(y[0], y[-1])
plt.xticks(x, rotation=90)
plt.yticks(y)
plt.show()
PS:为了让整数在单元格的中心(而不是在它们的边界)很好地刻度,需要进行以下更改:
triang1 = Triangulation(xs.ravel()-0.5, ys.ravel()-0.5, triangles1)
triang2 = Triangulation(xs.ravel()-0.5, ys.ravel()-0.5, triangles2)
# ...
plt.xlim(x[0]-0.5, x[-1]-0.5)
plt.ylim(y[0]-0.5, y[-1]-0.5)
plt.xticks(x[:-1], rotation=90)
plt.yticks(y[:-1])