Squarify — 如何调整树图矩形形状

Squarify — How to adjust treemap rectangle shapes

我在 Squarify 的文档中找不到编辑树图中矩形形状的方法。我想将其中一个矩形显示为其他矩形之一的正方形子集。这是我目前拥有的:

import squarify
from matplotlib import pyplot as plt

treemap_df = pd.DataFrame({
    'names': ['A', 'B', 'C'],
    'sizes': [25, 50, 75]
})

plt.figure(figsize=(10, 4))
ax = squarify.plot(
    treemap_df.sizes,
    label=treemap_df.names,
    color=["red","green","grey"],
    alpha=.8,
    edgecolor="white",
    linewidth=4
)

# I can get the coordinates of the squares/patches like this:
for rect in ax.patches:
    x, y, w, h = rect.get_x(), rect.get_y(), rect.get_width(), rect.get_height()
    c = rect.get_facecolor()
    print(f'Rectangle x={rect.get_x()} y={rect.get_y()} w={rect.get_width()} h={rect.get_height()} ')
    
plt.axis('off')
plt.title('Basic Treemap')
plt.show()

这给了我以下输出:

那么,假设我只想编辑绘图,使矩形 'A' 成为正方形 — 有什么办法可以做到这一点吗?理想情况下,我希望 'B' 的形状甚至不是正方形,但看起来 'A' 是矩形 'B' 的插入(这样它的形状就会变成 L 形)实际足迹),但只要能够调整矩形 shape/locations 就太好了。谢谢

下面的方法首先循环遍历矩形并保存矩形AB的位置。

然后,A的宽度和高度被修改为其乘积的平方根。

根据AB的坐标创建一个新的L形多边形,并复制B的属性。之后,B 被删除。

注意以下代码只对AB的特定位置起作用。其他位置将需要有点不同的 L 形,或者可能是不可能的。

另请注意,要使正方形看起来像正方形,需要等长宽比。 Squarify 使用参数 norm_xnorm_y,默认为 100,它们是周围矩形的尺寸。您可以将它们更改为具有不同的纵横比,但请注意,这可能会更改生成的矩形的位置。

import squarify
from matplotlib import pyplot as plt
from matplotlib.patches import Polygon
from math import sqrt

names = ['A', 'B', 'C']
sizes = [25, 50, 75]

plt.figure(figsize=(8, 6))
ax = squarify.plot(
    sizes,
    norm_x=100,
    norm_y=100,
    label=names,
    color=["red", "green", "grey"],
    alpha=.8,
    edgecolor="white",
    linewidth=4)

for rect, name in zip(ax.patches, names):
    (x, y), w, h = rect.get_xy(), rect.get_width(), rect.get_height()
    c = rect.get_facecolor()
    print(f'Rectangle {name} x={rect.get_x()} y={rect.get_y()} w={rect.get_width()} h={rect.get_height()} ')
    if name == 'A':
        rect_for_square = rect
        sq_size = sqrt(w * h)
        xa, ya = x, y
    if name == 'B':
        rect_for_L = rect
        xb, yb, wb, hb = x, y, w, h

rect_for_square.set_width(sq_size)
rect_for_square.set_height(sq_size)
points = [[xb, ya + sq_size], [xb, yb + hb], [xb + wb, yb + hb], [xb + wb, ya],
          [xb + sq_size, ya], [xb + sq_size, ya + sq_size], [xb, ya + sq_size]]

poly_L = Polygon(points, closed=True)
poly_L.update_from(rect_for_L) # copy colors, alpha, linewidths, ...
ax.add_patch(poly_L)

rect_for_L.remove()

ax.set_aspect('equal')
plt.axis('off')
plt.show()