Matplotlib 即使关联轴的纵横比不相等,如何使面片以相等的纵横比绘制?

Matplotlib 即使关联轴的纵横比不相等,如何使面片以相等的纵横比绘制?,matplotlib,Matplotlib,考虑以下玩具代码: # -*- coding: utf-8 -*- import numpy as np import matplotlib.pyplot as plt import matplotlib.patches as mpatches def draw_circle_arrangement(ax, drawing_origin, drawing_space, scale, num_circles, box_height, box_width): bw = drawing_sp

考虑以下玩具代码:

# -*- coding: utf-8 -*-
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.patches as mpatches

def draw_circle_arrangement(ax, drawing_origin, drawing_space, scale, num_circles, box_height, box_width):
    bw = drawing_space*(box_width*scale)

    drawing_origin[0] = drawing_origin[0] - bw*0.5

    circle_diameter = drawing_space*scale
    circle_radius = 0.5*circle_diameter
    y_delta = np.array([0., circle_diameter])
    x_delta = np.array([circle_diameter, 0.])

    cell_origin = drawing_origin + np.array([circle_radius, circle_radius])
    y_delta_index = 0
    x_delta_index = 0

    for ci in range(num_circles):
        cell_patch = mpatches.Circle(cell_origin + y_delta_index*y_delta + x_delta_index*x_delta, radius=circle_radius, color='k', fill=False, ls='solid', clip_on=False)
        ax.add_artist(cell_patch)

        if y_delta_index == box_height - 1:
            y_delta_index = 0
            x_delta_index += 1
        else:
            y_delta_index += 1


fig, ax = plt.subplots()

# each tuple is: number of circles, height of box containing circles, width of box containing circle
circle_arrangements = [(10, 2, 5), (3, 1, 3), (1, 1, 1)]
data = np.random.rand(3)
ax.set_ylim([0, 1])
ax.plot(np.arange(3) + 1, data, marker='o')
ax.get_xaxis().set_ticklabels([])
scale = 1./10.

for i, ca in enumerate(circle_arrangements):
    do = np.array([1.0 + i, -0.2])
    nc, bh, bw = ca
    draw_circle_arrangement(ax, do, 0.8, scale, nc, bh, bw)
运行时,它会生成如下输出:


正如你所看到的,这些圆不是圆!它们被压扁了。解决这一问题的一种方法是设置ax.set_aspect('equal'),但如果我不一定希望轴纵横比相等,那么如何仍能以这种方式生成面片?

不可能仅将部分轴纵横比设置为相等。解决方案可以是在不同的坐标系中绘制圆,或者使用使用不同坐标系的不同框

我认为后一种解决办法更可取。这需要使用
绘图区域
,该区域可以放在
注释框

import numpy as np
import matplotlib.pyplot as plt
import matplotlib.patches as mpatches
from matplotlib.offsetbox import  DrawingArea, AnnotationBbox

def draw_circle_arrangement(ax, drawing_origin, radius, 
                            num_circles, box_height, box_width):
    y_delta_index = 0
    x_delta_index = 0

    origin = np.array([radius,radius])
    y_delta = np.array([0., 2*radius])
    x_delta = np.array([2*radius, 0.])

    da = DrawingArea(box_width*2*radius, box_height*2*radius, 0, 0)

    for ci in range(num_circles):
        cell_patch = mpatches.Circle(origin+y_delta_index*y_delta + x_delta_index*x_delta, 
                                     radius=radius, color='k', fill=False, ls='solid',clip_on=False)
        da.add_artist(cell_patch)

        if y_delta_index == box_height - 1:
            y_delta_index = 0
            x_delta_index += 1
        else:
            y_delta_index += 1
    ab = AnnotationBbox(da, xy=(drawing_origin[0],0),
                        xybox=drawing_origin,
                        xycoords=("data", "axes fraction"),
                        boxcoords=("data", "axes fraction"),
                        box_alignment=(0.5,0.5), frameon=False)

    ax.add_artist(ab)


fig, ax = plt.subplots()
# each tuple is: number of circles, height of box containing circles, width of 
#box containing circle
circle_arrangements = [(10, 2, 5), (3, 1, 3), (1, 1, 1)]
data = np.random.rand(3)
ax.set_ylim([0, 1])
ax.plot(np.arange(3) + 1, data, marker='o')
ax.get_xaxis().set_ticklabels([])


for i, ca in enumerate(circle_arrangements):
    do = np.array([1.0 + i, -0.06])
    nc, bh, bw = ca
    draw_circle_arrangement(ax, do, 5, nc, bh, bw)

plt.show()


绘图区域的单位为点。例如,在第一种情况下,我们创建一个5*2*5=50点宽的绘图区域,并在其中放置5个半径为5点的圆(这5个圆填充了整个50点)。一个点约为1.4像素。注释框的位置以x位置的数据坐标和y位置的轴分数表示。这可以通过使用
boxcoords
参数进行更改。对于
xy
参数也是如此,在这里,我们确保y坐标位于0,因此位于轴内部(这样会显示注释框)

你能评论一下代码中的单位吗?我传递给
圆的图形坐标应该是什么单位?我传递给
绘图框
注释框
的坐标是什么;它们显然不是它们似乎暗示的数据坐标!我对代码做了一些小改动并添加了解释。我希望这样会更清楚。