matplotlib 在楔形图块(饼图)中保留纵横比

matplotlib preserve aspect ratio in Wedge patches (pie charts)

我想在特定位置绘制彩色饼图而不扭曲其圆形纵横比。我正在使用 Wedge 补丁,因为我找不到更好的解决方案。这是代码

import matplotlib.pyplot as plt
import numpy as np
from matplotlib import patches, collections

fig, axes = plt.subplots()
for i in range(20):
    x = np.random.uniform(low=0, high=1, size=10).cumsum()
    axes.scatter(x=x, y=np.repeat(i, x.shape[0]), c='gray', s=1)

pies = []
N = 4
cmap = plt.cm.get_cmap("hsv", N + 1)
colors = list(map(cmap, range(N)))
print(colors)

for i in range(2, 2 + N):
    thetas = np.linspace(0, 360, num=i)
    assert len(thetas) - 1 <= len(colors)
    for theta1, theta2, c in zip(thetas[:-1], thetas[1:], colors):
        wedge = patches.Wedge((i, i), r=i / 10, theta1=theta1, theta2=theta2,
                              color=c)
        pies.append(wedge)

axes.add_collection(collections.PatchCollection(pies,
                                                match_original=True))
plt.show()

如何保持饼图的纵横比?设置 axes.set_aspect("equal") 不是一个选项,因为当我有更多数据点时,它会完全压缩绘图。

我一直在查看 how to draw circles and preserve the aspect ratio 但这里无法采用解决方案 - 我正在绘制 Wedges/pie 图表,而不是圆圈。

我也看了 matplotlib transforms 但也没有找到答案。

当我设置 set_aspect('equal'):

时对我来说效果很好

我觉得 y-range 比 x-range 长,所以图片变窄了。

如果您将 y_lim 设置在 0 和小于 y_max 的数字之间,您会看得更清楚:


import matplotlib.pyplot as plt
import numpy as np
from matplotlib import patches, collections

fig, axes = plt.subplots()
for i in range(20):
    x = np.random.uniform(low=0, high=1, size=10).cumsum()
    axes.scatter(x=x, y=np.repeat(i, x.shape[0]), c='gray', s=1)

pies = []
N = 4
cmap = plt.cm.get_cmap("hsv", N + 1)
colors = list(map(cmap, range(N)))
print(colors)

for i in range(2, 2 + N):
    thetas = np.linspace(0, 360, num=i)
    assert len(thetas) - 1 <= len(colors)
    for theta1, theta2, c in zip(thetas[:-1], thetas[1:], colors):
        wedge = patches.Wedge((i, i), r=i / 10, theta1=theta1, theta2=theta2,
                              color=c)
        pies.append(wedge)

axes.add_collection(collections.PatchCollection(pies,
                                                match_original=True))
axes.set_aspect('equal')
axes.set_ylim(0,7.5)
plt.show()

我尝试了同样的事情,而 matplotlib 确实没有尝试让这对你来说很容易,但我找到了一个你应该能够使用的解决方案。

您需要将中心与楔形分开,并将它们作为偏移量添加到 PatchCollection 中。然后你可以对偏移量(transOffset)和形状(transform)应用不同的变换。

注意我已经更改了 r 值(半径)。此值不再位于数据坐标中,因此无论缩放多少,它都应始终保持相同大小,但它太小以至于无法在 i/10.

处看到
from matplotlib import patches, collections, transforms

offsets = []
for i in range(2, 2 + N):
    thetas = np.linspace(0, 360, num=i)
    assert len(thetas) - 1 <= len(colors)
    for theta1, theta2, c in zip(thetas[:-1], thetas[1:], colors):
        wedge = patches.Wedge((0, 0), r=10, theta1=theta1, theta2=theta2,
                              color=c)
        offsets.append((i, i))
        pies.append(wedge)

coll = collections.PatchCollection(
    pies, match_original=True, offsets=offsets,
    transform=transforms.IdentityTransform(),
    transOffset=axes.transData
)