Сложность совмещения и перестановки легенд двух графиков в matplotlib и pandas - PullRequest
2 голосов
/ 22 февраля 2020

Я пытаюсь построить две диаграммы на одной фигуре, причем обе диаграммы исходят из одного и того же кадра данных, но одна представлена ​​в виде гистограммы с накоплением, а другая - в виде простого линейного графика.

При создании графика используя следующий код:

combined.iloc[:, 1:10].plot(kind='bar', stacked=True, figsize=(20,10))
combined.iloc[:, 0].plot(kind='line', secondary_y=True, use_index=False, linestyle='-', marker='o')
plt.legend(loc='upper left', fancybox=True, framealpha=1, shadow=True, borderpad=1)
plt.show()

С фреймом данных combined, похожим на это:

source data frame

Я получаю следующее image:

stacked bar chart with line number of CVEs overlaid

Я пытаюсь объединить обе легенды в одну и расположить легенду в верхнем левом углу, чтобы была видна вся диаграмма.

Может кто-нибудь объяснить, почему plt.legend() только редактирует линейную диаграмму, соответствующую срезу combined.iloc[:, 0] моего combined кадра данных? Если кто-нибудь может увидеть быстрый и простой способ комбинирования и изменения положения легенд, пожалуйста, дайте мне знать! Я был бы очень признателен.

1 Ответ

1 голос
/ 23 февраля 2020

Передача True для аргумента secondary_y означает, что график будет создан на отдельном экземпляре осей с двойной осью X, так как это создает другой экземпляр оси, поэтому обычно решение заключается в создании легенды вручную, как в ответы на вопрос связаны @ ImportanceOfBeingErnest . Если вы не хотите создавать легенду напрямую, вы можете обойти эту проблему, вызывая plt.legend() между вызовами pandas.DataFrame.plot и сохраняя результат. Затем вы можете восстановить маркеры и метки из двух экземпляров осей. Следующий код является полным примером этого

import pandas as pd
import matplotlib.pyplot as plt
import numpy as np

df = pd.DataFrame({'x' : np.random.random(25), 
                   'y' : np.random.random(25)*5, 
                   'z' : np.random.random(25)*2.5})

df.iloc[:, 1:10].plot(kind='bar', stacked=True)
leg = plt.legend()
df.iloc[:, 0].plot(kind='line', y='x', secondary_y=True)
leg2 = plt.legend()
plt.legend(leg.get_patches()+leg2.get_lines(), 
           [text.get_text() for text in leg.get_texts()+leg2.get_texts()], 
           loc='upper left', fancybox=True, framealpha=1, shadow=True, borderpad=1)
leg.remove()
plt.show()

. Это приведет к

enter image description here

и его должно быть довольно легко изменить подходит вашему конкретному c сценарию использования.

...