Во-первых, хороший вопрос! Вы погружаетесь в подробные детали, поэтому есть довольно много полудокументированных деталей, которые вам нужно знать.
Ваш текущий метод будет работать за исключением двух вещей:
clip_box
, как ожидается, будет в координатах дисплея, так что вам нужно, чтобы преобразовать его.
- Для этого недостаточно использовать «равнину»
Bbox
. Для преобразования координат данных, которые необходимо переделать каждый раз при изменении дисплея, вам необходимо использовать TransformedBbox
.
Чтобы продемонстрировать немного больше того, что происходит, давайте исправим первую проблему, но не второй:
import matplotlib.pyplot as plt
from matplotlib.transforms import Bbox
fig, ax = plt.subplots()
vals = [
(10,20,"Lorem ipsum dolor sit amet, consectetur adipiscing elit"),
(30,20, "Pellentesque scelerisque congue fermentum."),
(50,10, "Aliquam erat volutpat")
]
ax.set_ylim(0,1)
ax.broken_barh(map(lambda v: v[:2],vals), (0, 1),
facecolors=('yellow','red','green'))
for v in vals:
box = Bbox([[v[0],0],[v[0]+v[1],1]]).transformed(ax.transData)
anno = ax.annotate(v[2], xy=(v[0],0.4), clip_box=box)
plt.show()
Он хорошо выглядит на первый, но есть еще одна проблема : Поскольку clip_box
является статическим и в координатах отображения, он будет находиться в неправильном положении, как только вы измените сюжет каким-либо образом (например, масштабирование, панорамирование, автомасштабирование, изменение размера окна фигуры, изменение фигуры DPI).
Например, если я нажал кнопку «Сохранить» (или позвонил savefig
), поле клипа будет неправильным, потому что DPI рисунка будет изменен (от 80 до 100) перед сохранением!
По этой причине, вы должны использовать TransformedBbox
для этого. Это всего лишь версия Bbox
, которая сохраняет ссылку на преобразование и преобразует базовый Bbox
, если изменение изменится. Есть несколько классов Transformed*
по этим линиям в matplotlib: например. TransformedPath
и т. Д. Они не являются уровнем детализации, о котором вы всегда должны знать, но они могут быть очень полезными.
В качестве последнего примера, что не будет работать правильно, независимо от того, как масштабируется сюжет/панорамирование/изменено:
import matplotlib.pyplot as plt
from matplotlib.transforms import TransformedBbox, Bbox
fig, ax = plt.subplots()
vals = [
(10,20,"Lorem ipsum dolor sit amet, consectetur adipiscing elit"),
(30,20, "Pellentesque scelerisque congue fermentum."),
(50,10, "Aliquam erat volutpat")
]
ax.set_ylim(0,1)
ax.broken_barh(map(lambda v: v[:2],vals), (0, 1),
facecolors=('yellow','red','green'))
for v in vals:
box = TransformedBbox(Bbox([[v[0],0],[v[0]+v[1],1]]), ax.transData)
anno = ax.annotate(v[2], xy=(v[0],0.4), clip_box=box)
plt.show()
Что такое использование случай, когда вы используете 'broken_bar_h'? – tacaswell
Я нашел его идеальным инструментом для визуализации телешоу ([пример] (http://cl.ly/image/0T3g2A301b3r)). Некоторое время назад я делал подобное в ggplot, и там я полагался на 'aes (xmin =, xmax =, ymin =, ymax =)' – trnl
Интересно. Это довольно крутая фигура! – tacaswell