Matplotlib: построить линию с открытыми маркерами, где линия не видна внутри маркеров - PullRequest
4 голосов
/ 21 октября 2019

У меня есть точечная диаграмма, показывающая набор данных с символами, раскрашенными в соответствии с некоторой цветовой шкалой. Я хочу выделить некоторые из этих точек, нарисовав вокруг них открытый круг и соединив их линией. Другими словами, в очень упрощенном примере я хочу, чтобы результат выглядел так:

a scatter plot with coloured data and a few highlighted points, connected by a line, where the line segments inside the symbols are hidden from view.

Я могу сделать график, похожий на этот, используя следующий код:

import numpy as np
import matplotlib.pyplot as plt

fig, ax = plt.subplots(figsize=(5,5))

X, Y = np.meshgrid(np.arange(10), np.arange(10))
Z = X**2 + Y**2

plt.scatter(X,Y,c=Z, s=300, cmap='viridis_r')

plt.plot([1, 4, 7], [7, 1, 4], 'k-o', linewidth=3, 
         markersize=14, markerfacecolor='none', markeredgewidth=2, 
        )

Однако результат выглядит так:

a scatter plot with coloured data and a few highlighted points, connected by a line.

Мне бы хотелось, чтобы отрезки линии были в пределах символа маркера, который должен быть скрыт от просмотра. Это потому, что я заинтересован в привлечении внимания к конкретным точкам данных и не хочу частично скрывать их от глаз.

Обходные пути могут быть:

  1. , чтобы дублировать точки данных, которые я хочу выделить, и закрасить маркеры точно таким же цветом, как и исходный символ, который скрывает маркер. Это неудовлетворительно, потому что (а) у меня не всегда есть доступ к данным, только к выходному рисунку или экземпляру оси, и (б) я не знаю, как это сделать в случае полупрозрачных символов,что имеет место в моем фактическом наборе данных.
  2. , чтобы вручную вычислить адаптированные координаты, чтобы сделать соединительные линии такими, чтобы они доходили только до края маркеров. Это также кажется довольно неудовлетворительным (и я не знаю, как это сделать, учитывая, что система координат оси и символов не будет одинаковой).

Мой вопрос: что будет лучшим путем? Есть ли лучший способ, чем варианты 1 и 2, описанные выше, и если нет, то какой будет наилучшим? Как уже говорилось, с 1 я предвижу проблемы с прозрачностью (которую я использую), а с 2 я предвижу проблемы с системой координат, например, в случае увеличения или уменьшения масштаба и т. Д.

(другой маленькийнаблюдение в моем примере, о котором я немного запутался: plt.plot и plt.scatter, кажется, не изображают вещи в одном и том же месте ( см. этот рисунок ), а также определение размера противоречиво)

1 Ответ

3 голосов
/ 21 октября 2019

Вы хотите получить прозрачные (открытые) круги, расположенные в координатах данных, но с радиусом в точках. Вы хотите соединить круги друг с другом, а не центральные точки. Это означает, что вы не можете использовать обычную линию. Вместо этого несколько ConnectionPatch могут помочь. Вы можете уменьшить их вдвое, чтобы они касались границы кругов.

import numpy as np
import matplotlib.pyplot as plt
from matplotlib.patches import ConnectionPatch

fig, ax = plt.subplots(figsize=(5,5))

X, Y = np.meshgrid(np.arange(10), np.arange(10))
Z = X**2 + Y**2

ax.scatter(X,Y,c=Z, s=300, cmap='viridis_r')

xc = [1, 4, 7]
yc = [7, 1, 4]

ax.plot(xc, yc, linewidth=0, marker="o", color="black",
         markersize=np.sqrt(300), markerfacecolor='none', markeredgewidth=3)

for i in range(len(xc)-1):
    cp = ConnectionPatch((xc[i],yc[i]), (xc[i+1], yc[i+1]), 
                         coordsA='data', coordsB='data', axesA=ax, axesB=ax,
                         shrinkA=np.sqrt(300)/2, shrinkB=np.sqrt(300)/2,
                         linewidth=2)
    ax.add_patch(cp)

plt.show()

enter image description here

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...