1

我使用 Matplotlib 和 Squarify 创建了这个树图: 在此处输入图像描述

现在我想在树图中的每个矩形上添加一个线图。那可能吗?

4

2 回答 2

1

对的,这是可能的。您必须编写代码来提取要放置新绘图的确切位置。

您需要使用设置新图形的位置f.canvas.manager.window.SetPosition

这个答案将极大地帮助https://stackoverflow.com/a/37999370/4551984

于 2020-04-01T08:09:43.393 回答
1

Squarify的 plot 是一个方便的函数,可以直接绘制给定值和标签的树形图。但是,这个过程也可以逐步执行。其中一个步骤是计算矩形的位置,我们假设一个图形的坐标从左下到右上从 0,0 到 1,1。

使用这些矩形,我们可以手动定位要绘制的轴。目前还不清楚是否需要蜱虫。如果需要,它们可以放在里面。或者轴可以完全移动到每个子图的中心。或者只有没有标签的刻度。

下面是一些演示代码:

import numpy as np
import matplotlib.pyplot as plt
import squarify

values = [500, 433, 331, 254, 119]
values.sort(reverse=True)  # values must be sorted descending (and positive)
# the sum of the values must equal the total area to be laid out; i.e., sum(values) == width * height
values = squarify.normalize_sizes(values, 1, 1)
rects = squarify.squarify(values, 0, 0, 1, 1)

fig = plt.figure(figsize=(7, 5))

axes = [fig.add_axes([rect['x'], rect['y'], rect['dx'], rect['dy'], ]) for rect in rects]

for ax, color in zip(axes, plt.cm.Pastel1.colors):
    x = np.linspace(0, 10, 100)
    y = np.random.normal(0.01, 0.1, 100).cumsum()
    ax.plot(x, y)
    ax.tick_params(axis="y", direction="in", pad=-15)
    ax.tick_params(axis="x", direction="in", pad=-15)
    plt.setp(ax.get_yticklabels(), ha="left")
    ax.set_facecolor(color)
plt.show()

结果图

这是另一个类似于问题中图像的示例,带有主图和颜色条。默认的 mplcursors 会与所有这些轴混淆,但也可以手动添加悬停时的注释。

import numpy as np
import matplotlib.pyplot as plt
import squarify

values = [4000, 1500, 1500, 1200, 1000, 500]

fig, mainax = plt.subplots(figsize=(6, 4))

mainax.set_xlim(0, 1000)
mainax.set_ylim(0, 1000)
mainax.grid(False)
cmap = plt.cm.get_cmap('Greens')
norm = plt.Normalize(vmin=0, vmax=max(values))
plt.colorbar(plt.cm.ScalarMappable(cmap=cmap, norm=norm))
pos = mainax.get_position()

values.sort(reverse=True)
normalized_values = squarify.normalize_sizes(values, pos.width, pos.height)
rects = squarify.squarify(normalized_values, pos.x0, pos.y0, pos.width, pos.height)

axes = [fig.add_axes([rect['x'], rect['y'], rect['dx'], rect['dy'], ]) for rect in rects]

for ax, val in zip(axes, values):
    x = np.linspace(0, 10, 100)
    y = np.random.normal(0.01, 0.1, 100).cumsum()
    ax.plot(x, y)
    ax.set_xticks([])
    ax.set_yticks([])
    ax.set_facecolor(cmap(norm(val)))
mainax.set_facecolor('none') # prevent that the mainax blocks the other axes
mainax.set_zorder(20) # high z-order because the annotations are drawn using this ax

labels = ['a', 'b', 'c', 'd', 'e', 'f']
sum_val = sum(values)
annotations = [mainax.annotate(f"'{lbl}': {val}\n{val * 100.0 / sum_val:.1f} %",
                               xy=(0, 0), xycoords='figure pixels',
                               xytext=(0, 0), textcoords='offset points',
                               bbox=dict(boxstyle='round', fc='lemonchiffon'),
                               ha='center', va='bottom')
               for ax, val, lbl in zip(axes, values, labels)]
for annot in annotations:
    annot.set_visible(False)

def hover(event):
    for ax, annot in zip(axes, annotations):
        if ax.bbox.contains(event.x, event.y):
            annot.xy = (event.x, event.y)
            annot.set_visible(True)
        else:
            annot.set_visible(False)
    fig.canvas.draw_idle()

fig.canvas.mpl_connect("motion_notify_event", hover)

plt.show()

用彩条绘制

于 2020-04-01T10:00:04.117 回答