【问题标题】:matplotlib preserve aspect ratio in Wedge patches (pie charts)matplotlib 在 Wedge 补丁中保留纵横比(饼图)
【发布时间】:2020-10-31 18:34:14
【问题描述】:

我想在不扭曲圆形纵横比的情况下在特定位置绘制彩色饼图。我正在使用 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,但这里无法采用该解决方案 - 我正在绘制楔形/饼图,而不是圆形。

我也查看了matplotlib transforms,但在那里也找不到答案。

【问题讨论】:

    标签: python matplotlib pie-chart


    【解决方案1】:

    我尝试了同样的事情,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
    )
    

    【讨论】:

    • 我需要仔细研究您的解决方案才能理解它,但它确实有效。
    【解决方案2】:

    当我设置set_aspect('equal')时它对我来说很好:

    图像变窄了,因为我认为 y 范围比 x 范围长。

    如果您将 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()
    

    【讨论】:

    • 这正是我不想要的——我在我的问题中明确指出axes.set_aspect("equal") 不是解决方案。通过削减 ymax,您会丢失数据。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-07-16
    • 1970-01-01
    • 2013-11-17
    • 1970-01-01
    • 2014-06-17
    相关资源
    最近更新 更多