Вопрос или проблема
У меня есть следующий код:
import pandas as pd
import seaborn as sns
import matplotlib.pyplot as plt
v_exponents = range(2, 9)
vs = [2 ** exponent - 1 for exponent in v_exponents]
df = pd.read_csv('data/out/erdos_renyi_graph/path_lengths_dfs/stats.csv')
for v in vs:
df_filtered = df[df['V'] == v]
print(df_filtered)
sns.lineplot(data=df_filtered, x="E", y="fraction_connected")
plt.legend(title="V", labels=vs)
plt.savefig(f'src/main/python/erdos_renyi_graph/path_lengths_dfs/doc/img/ErdosRenyiGraph-PathLengthsDFS.png')
Это дает такой вывод:
Почему легенда испорчена? Есть чередующиеся тонкие и толстые линии, по две каждого цвета. Более того, не отображаются все цвета, только от синего до красного.
import pandas as pd
import seaborn as sns
import matplotlib.pyplot as plt
v_exponents = range(2, 9)
vs = [2 ** exponent - 1 for exponent in v_exponents]
df = pd.read_csv('data/out/erdos_renyi_graph/path_lengths_dfs/stats.csv')
labels = []
fig, ax = plt.subplots()
for v in vs:
df_filtered = df[df['V'] == v]
print(df_filtered)
sns.lineplot(data=df_filtered, x="E", y="fraction_connected", label=v)
handles, labels = ax.get_legend_handles_labels()
# Создать одну легенду
ax.legend(handles, labels)
plt.savefig(f'src/main/python/erdos_renyi_graph/path_lengths_dfs/doc/img/ErdosRenyiGraph-PathLengthsDFS.png')
.
Ответ или решение
Проблема, о которой вы упомянули, заключается в том, что легенда вашего графика соответствует не всем линиям на графике и отображается некорректно. Давайте подробно рассмотрим, почему это происходит и как можно исправить данную ситуацию.
Причины проблемы
-
Многократный вызов
sns.lineplot
: В вашем первом блоке кода, каждый раз, когда вы вызываетеsns.lineplot
, вы не указываете явно метку (label
) для каждой линии. Это приводит к тому, что для всех линий, добавляемых на график, создаются разные объектыline
, и в итоге в легенде отображаются только последние добавленные линии. Кроме того,plt.legend()
пытается создать легенду на основании линий, но поскольку они все с одинаковым цветом, это создает путаницу. -
Отсутствие корректной обработки объектов осей: Легенда генерируется на основе объектов, созданных на текущих осях. Если вы вызываете
plt.legend()
без явного указания объектов оси (например, используяax.get_legend_handles_labels()
), это может привести к неочевидным результатам.
Решения
Чтобы устранить указанную вами проблему, следует внести некоторые изменения в код. Рассмотрим обновленный фрагмент кода:
import pandas as pd
import seaborn as sns
import matplotlib.pyplot as plt
# Определяем диапазон значений V
v_exponents = range(2, 9)
vs = [2 ** exponent - 1 for exponent in v_exponents]
# Загружаем данные
df = pd.read_csv('data/out/erdos_renyi_graph/path_lengths_dfs/stats.csv')
# Создаем объект фигуры и осей
fig, ax = plt.subplots()
# Проходим по каждому значению V и строим линии
for v in vs:
df_filtered = df[df['V'] == v]
sns.lineplot(data=df_filtered, x="E", y="fraction_connected", ax=ax, label=str(v))
# Получаем обработки и метки для легенды
handles, labels = ax.get_legend_handles_labels()
ax.legend(handles, labels, title="V")
# Сохраняем график
plt.savefig(f'src/main/python/erdos_renyi_graph/path_lengths_dfs/doc/img/ErdosRenyiGraph-PathLengthsDFS.png')
Объяснение изменений
-
Добавление меток в
lineplot
: В строкеsns.lineplot(...)
, мы добавили параметрlabel=str(v)
, который гарантирует, что каждая линия получит свою уникальную метку, соответствующую значениюV
. -
Работа с объектом осей: Мы используем аргумент
ax=ax
вsns.lineplot
, чтобы убедиться, что все линии добавляются на один и тот же объект осей. Это помогает централизовать управляемые элементы графика и делает их более управляемыми. -
Создание легенды на основе объектов осей: Команда
handles, labels = ax.get_legend_handles_labels()
позволяет корректно получить все сохраненные ручки и метки из объекта осей, что будет гарантировать, что все линии будут правильно отображены в легенде.
Заключение
С применением этих изменений вы получите корректную легенду, соответствующую всем линиям на графике. Если у вас есть еще вопросы по конкретным аспектам, не стесняйтесь их задавать.