#python #matplotlib #plot #seaborn #legend
Вопрос:
Я хочу переименовать и переместить две легенды. Я хочу, чтобы верхняя легенда была вне графика, вверху справа и озаглавлена 'Average Cost'
. Я хочу, чтобы вторая легенда была вне графика, внизу справа и называлась 'Total Revenue'
figure = plt.figure(figsize=(10,5))
ax = sns.scatterplot(
x=top_rev_mean['cost_of_the_order_y'],
y='cost_of_the_order_x',
data=top_rev_mean,
size = "cost_of_the_order_x",
hue='cost_of_the_order_y'
)
plt.ylabel('Total Order Revenue')
plt.xlabel('Average Order Cost Per Cuisine')
plt.show()
Ответ №1:
Я полагаю, вы работаете с таким фреймом данных, как этот:
import matplotlib.pyplot as plt
import seaborn as sns
import numpy as np
import pandas as pd
N = 15
top_rev_mean = pd.DataFrame({'cost_of_the_order_y': 17.6 4*np.random.random(N),
'cost_of_the_order_x': 500 2000*np.random.random(N)})
cost_of_the_order_y cost_of_the_order_x
0 19.098160 866.809020
1 21.402857 1108.484486
2 20.527976 1549.512863
3 19.994634 1363.890037
4 18.224075 1082.458280
5 18.223978 1723.705789
6 17.832334 778.987721
7 21.064705 1084.289297
8 20.004460 1232.723687
9 20.432290 1412.139968
10 17.682338 2070.351923
11 21.479639 899.347564
12 20.929771 1528.468877
13 18.449356 1684.829138
14 18.327300 592.900825
Когда вы настраиваете диаграмму рассеяния, вы должны быть уверены, что легенда нарисована, чтобы позже получить маркеры и метки, поэтому вам нужно передать legend = True
параметр в seaborn.scatterplot
:
fig, ax = plt.subplots(figsize=(10,5))
sns.scatterplot(ax = ax, data = top_rev_mean, x = 'cost_of_the_order_y', y = 'cost_of_the_order_x', size = "cost_of_the_order_x", hue = 'cost_of_the_order_y', legend = True)
Затем вы можете извлечь дескрипторы и метки текущей легенды с помощью ax.get_legend_handles_labels
:
handles, labels = ax.get_legend_handles_labels()
Теперь вам нужно разделить элементы первой легенды от элементов второй:
legend1 = {}
legend2 = {}
titles = {}
for handle, label in zip(handles, labels):
if label.replace('.', '').isdigit() == False:
titles[handle] = label
else:
if len(list(titles.keys())) == 1:
legend1[handle] = label
else:
legend2[handle] = label
Наконец, вы можете удалить легенду, нарисованную из сиборна, и нарисовать две легенды, которые вы хотите:
ax.legend().remove()
upper_legend = ax.legend(handles = list(legend1.keys()), labels = list(legend1.values()), title = 'Average Cost', loc = 'upper left', bbox_to_anchor = (1.05, 1))
ax.add_artist(upper_legend)
lower_legend = ax.legend(handles = list(legend2.keys()), labels = list(legend2.values()), title = 'Total Revenue', loc = 'lower left', bbox_to_anchor = (1.05, 0))
Полный Код
import matplotlib.pyplot as plt
import seaborn as sns
import numpy as np
import pandas as pd
N = 15
top_rev_mean = pd.DataFrame({'cost_of_the_order_y': 17.6 4*np.random.random(N),
'cost_of_the_order_x': 500 2000*np.random.random(N)})
fig, ax = plt.subplots(figsize=(10,5))
sns.scatterplot(ax = ax, data = top_rev_mean, x = 'cost_of_the_order_y', y = 'cost_of_the_order_x', size = "cost_of_the_order_x", hue = 'cost_of_the_order_y', legend = True)
handles, labels = ax.get_legend_handles_labels()
legend1 = {}
legend2 = {}
titles = {}
for handle, label in zip(handles, labels):
if label.replace('.', '').isdigit() == False:
titles[handle] = label
else:
if len(list(titles.keys())) == 1:
legend1[handle] = label
else:
legend2[handle] = label
ax.legend().remove()
upper_legend = ax.legend(handles = list(legend1.keys()), labels = list(legend1.values()), title = 'Average Cost', loc = 'upper left', bbox_to_anchor = (1.05, 1))
ax.add_artist(upper_legend)
lower_legend = ax.legend(handles = list(legend2.keys()), labels = list(legend2.values()), title = 'Total Revenue', loc = 'lower left', bbox_to_anchor = (1.05, 0))
ax.set_ylabel('Total Order Revenue')
ax.set_xlabel('Average Order Cost Per Cuisine')
plt.tight_layout()
plt.show()
Комментарии:
1. Это прекрасно. Спасибо!