我正在尝试绘制一个由5 x 6个子图组成的图形,这些图我都希望相邻,即共享它们的x和y轴。
我还想在每行的最右边绘图中添加一个颜色条,该颜色条已针对该行中的所有子图进行了标准化。
我使用以下方法添加颜色条:
<!DOCTYPE html>
<html>
<head>
<script src="http://d3js.org/d3.v4.min.js"></script>
</head>
<body>
<div id="grid"></div>
<script>
//creat 1670 numbers of matrices with size of 180*90
var myMatrix = new Array(1670)
for (var i = 0; i < 1670; i++) {
myMatrix[i] = twodmatrix()
}
function twodmatrix() {
var myMat = new Array(180)
for (var i = 0; i < 180; i++) {
myMat[i] = new Array(90)
}
return (myMat)
}
//read from file
d3.text("tempanomaly_new.txt", function(data) {
myMatrix = data
})
// save the values of one matrix in color matrix
const NUM_COLOR = 16200;
var colorArr = new Array(NUM_COLOR);
for (var i = 0; i < NUM_COLOR; i++) {
colorArr[i] = getColor();
}
function getColor() {
color = "#" + [Math.floor(Math.values(myMatrix) * 16)];
return color;
}
const BLOCK_SIZE = 30;
const BLOCK_SPACE = 5;
var gridData = new Array(180)
for (var i = 0; i < 180; i++) {
gridData[i] = new Array(90)
for (var j = 0; j < 90; j++) {
gridData[i][j] = {
x: (i + 1) * BLOCK_SIZE + BLOCK_SPACE,
y: (j + 1) * BLOCK_SIZE + BLOCK_SPACE,
size: BLOCK_SIZE,
color: colorArr[(i * 10 + j) % NUM_COLOR]
}
}
}
var grid = d3.select("#grid")
.append("svg")
.attr("width", "100%")
.attr("height", "100%")
.style("color", "#b2b2b2");
var row = grid.selectAll(".row")
.data(gridData)
.enter().append("g")
.attr("class", "row");
var column = row.selectAll(".square")
.data(function(data) {
return data;
})
.enter()
.append("rect")
.attr("class", "square")
.attr("x", function(data) {
return data.x;
})
.attr("y", function(data) {
return data.y;
})
.attr("width", function(data) {
return data.size;
})
.attr("height", function(data) {
return data.size;
})
.style("fill", function(data) {
return data.color;
})
.style("stroke", "#222");
</script>
</body>
</html>
但是,添加颜色栏会更改子图的大小,并且不再粘到其他子图上。这是一个示例输出: 添加彩条时如何不改变尺寸?
以下是生成上面图像的代码示例:
divider = make_axes_locatable(ax)
cax = divider.append_axes("right", size="5%", pad=0.15)
fig.colorbar(im, cax=cax)
答案 0 :(得分:0)
实际上,下面来自用户ImportanceOfBeingErnest的注释并使用axes_grid1,我可以使其正常工作。
主要区别:对于每一行,我定义一个ImageGrid
对象:
axrows = [[] for r in range(nrows)]
i = 0
for r in range(nrows):
axcols = [None for c in range(ncols)]
axcols = ImageGrid(fig, (nrows, 1, r+1),
nrows_ncols=(1, ncols),
axes_pad = 0.0,
share_all = True,
label_mode = 'L',
cbar_mode = 'edge',
cbar_location = 'right',
cbar_size = "7%",
cbar_pad = "2%")
axrows[r] = axcols
然后,在代码中的正确位置,我将色条添加为
axcols.cbar_axes[0].colorbar(im)
这是完整的代码:
#!/usr/bin/env python3
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.colors
from mpl_toolkits.axes_grid1 import make_axes_locatable, axes_size
from mpl_toolkits.axes_grid1 import ImageGrid
# border limits for plots
lowlim = 0.43
uplim = 0.52
nx = 10
kernels = ['cubic_spline', 'quintic_spline',
'wendland_C2', 'wendland_C4', 'wendland_C6']
#========================
def main():
#========================
eta_facts = [ 0, 1, 2, 3, 4, 5 ]
nrows = len(eta_facts)
ncols = len(kernels)
Ay_list = [[None for c in range(ncols)] for r in range(nrows)]
#--------------------------------
# Loop and compute As
#--------------------------------
dx = (uplim - lowlim)/nx
for row, eta in enumerate(eta_facts):
for col, kernel in enumerate(kernels):
A = np.zeros((nx, nx), dtype=np.float)
for i in range(nx):
for j in range(nx):
A[j,i] = row + np.random.random()/10 # not a typo: need A[j,i] for imshow
Ay_list[row][col] = A
#------------------------------------
# Now plot it
#------------------------------------
fig = plt.figure(figsize=(3.5*ncols+1, 3.5*nrows))
axrows = [[] for r in range(nrows)]
i = 0
for r in range(nrows):
axcols = [None for c in range(ncols)]
axcols = ImageGrid(fig, (nrows, 1, r+1),
nrows_ncols=(1, ncols),
axes_pad = 0.0,
share_all = True,
label_mode = 'L',
cbar_mode = 'edge',
cbar_location = 'right',
cbar_size = "7%",
cbar_pad = "2%")
axrows[r] = axcols
cmap = 'YlGnBu_r'
lw = 2
for row in range(nrows):
axcols = axrows[row]
minval = min([np.min(Ay_list[row][c]) for c in range(ncols)])
maxval = max([np.max(Ay_list[row][c]) for c in range(ncols)])
for col, ax in enumerate(axcols):
im = ax.imshow(Ay_list[row][col], origin='lower',
vmin=minval, vmax=maxval, cmap=cmap,
extent=(lowlim, uplim, lowlim, uplim),
# norm=matplotlib.colors.SymLogNorm(1e-3),
zorder=1)
ax.set_xlim((lowlim,uplim))
ax.set_ylim((lowlim,uplim))
# cosmetics
if col > 0:
left = False
else:
left = True
if row == len(eta_facts)-1 :
bottom = True
else:
bottom = False
ax.tick_params(
axis='both', # changes apply to the x-axis
which='both', # both major and minor ticks are affected
bottom=bottom, # ticks along the bottom edge are off
top=False, # ticks along the top edge are off
left=left, # ticks along the left edge are off
right=False, # ticks along the rigt edge are off
labelbottom=bottom, # labels along the bottom edge are off
labeltop=False, # labels along the top edge are off
labelleft=left, # labels along the left edge are off
labelright=False) # labels along the right edge are off
if row==0:
ax.set_title(kernels[col] + ' kernel', fontsize=14)
if col==0:
ax.set_ylabel(r"$\eta = $ "+str(eta_facts[row])+r"$\eta_0$")
axcols.cbar_axes[0].colorbar(im)
fig.suptitle(r"Some title", fontsize=18)
plt.tight_layout(rect=(0, 0, 1, 0.97))
plt.subplots_adjust(wspace=0.0, hspace=0.0)
plt.savefig('for_stackexchange.png', dpi=150)
plt.close()
print('finished.')
return
if __name__ == '__main__':
main()
哪个产生这张图片: