簡體   English   中英

為 matplotlib、seaborn 中的多個 plot 創建單個圖例

[英]Create a single legend for multiple plot in matplotlib, seaborn

我正在使用“iris.csv”數據制作箱線圖。 我試圖通過測量(即花瓣長度、花瓣寬度、萼片長度、萼片寬度)將數據分解為多個 dataframe,然后在 forloop 上制作箱線圖,從而添加子圖。

最后,我想一次為所有框 plot 添加一個通用圖例。 但是,我做不到。 我已經使用幾個 stackoverflow 問題嘗試了幾個教程和方法,但我無法修復它。

這是我的代碼:

import seaborn as sns 
from matplotlib import pyplot

iris_data = "iris.csv"
names = ['sepal-length', 'sepal-width', 'petal-length', 'petal-width', 'class']
dataset = read_csv(iris_data, names=names)


# Reindex the dataset by species so it can be pivoted for each species 
reindexed_dataset = dataset.set_index(dataset.groupby('class').cumcount())
cols_to_pivot = ['sepal-length', 'sepal-width', 'petal-length', 'petal-width']

# empty dataframe 
reshaped_dataset = pd.DataFrame()
for var_name in cols_to_pivot:
    pivoted_dataset = reindexed_dataset.pivot(columns='class', values=var_name).rename_axis(None,axis=1)
    pivoted_dataset['measurement'] = var_name
    reshaped_dataset = reshaped_dataset.append(pivoted_dataset, ignore_index=True)


## Now, lets spit the dataframe into groups by-measurements.
grouped_dfs_02 = []
for group in reshaped_dataset.groupby('measurement') :
    grouped_dfs_02.append(group[1])


## make the box plot of several measured variables, compared between species 

pyplot.figure(figsize=(20, 5), dpi=80)
pyplot.suptitle('Distribution of floral traits in the species of iris')

sp_name=['Iris-setosa', 'Iris-versicolor', 'Iris-virginica']
setosa = mpatches.Patch(color='red')
versi = mpatches.Patch(color='green')
virgi = mpatches.Patch(color='blue')

my_pal = {"Iris-versicolor": "g", "Iris-setosa": "r", "Iris-virginica":"b"}
plt_index = 0


# for i, df in enumerate(grouped_dfs_02):
for group_name, df in reshaped_dataset.groupby('measurement'):

    axi = pyplot.subplot(1, len(grouped_dfs_02), plt_index + 1)
    sp_name=['Iris-setosa', 'Iris-versicolor', 'Iris-virginica']
    df_melt = df.melt('measurement', var_name='species', value_name='values')

    sns.boxplot(data=df_melt, x='species', y='values', ax = axi, orient="v", palette=my_pal)
    pyplot.title(group_name)
    plt_index += 1


# Move the legend to an empty part of the plot
pyplot.legend(title='species', labels = sp_name, 
         handles=[setosa, versi, virgi], bbox_to_anchor=(19, 4),
           fancybox=True, shadow=True, ncol=5)


pyplot.show()

這是 plot: 在此處輸入圖像描述

如何,我如何在“主字幕”旁邊的主圖外添加一個常見的圖例?

對於 position 的圖例,設置loc參數很重要,即定位點。 (默認loc'best' ,這意味着您事先不知道它會在哪里結束)。 位置的測量范圍是從當前軸的左下角0,0到當前軸的左上角1,1 這不包括標題等的填充,因此值可以 go 有點超出0, 1范圍。 “當前斧頭”是最后一個被激活的斧頭。

請注意,您還可以使用plt.gcf().legend代替plt.legend (使用軸),它使用“圖形”。 然后,坐標在完整的 plot(“圖”)的左下角為0,0 ,在右上角為1,1 一個缺點是不會為圖例創建額外的空間,因此您需要手動設置頂部填充(例如plt.gcf().subplots_adjust(top=0.8) )。 一個缺點是您不能再使用plt.tight_layout() ,並且將圖例與軸對齊會更加困難。

import seaborn as sns
from matplotlib import pyplot as plt
from matplotlib import patches as mpatches
import pandas as pd

dataset = sns.load_dataset("iris")

# Reindex the dataset by species so it can be pivoted for each species
reindexed_dataset = dataset.set_index(dataset.groupby('species').cumcount())
cols_to_pivot = ['sepal_length', 'sepal_width', 'petal_length', 'petal_width']

# empty dataframe
reshaped_dataset = pd.DataFrame()
for var_name in cols_to_pivot:
    pivoted_dataset = reindexed_dataset.pivot(columns='species', values=var_name).rename_axis(None, axis=1)
    pivoted_dataset['measurement'] = var_name
    reshaped_dataset = reshaped_dataset.append(pivoted_dataset, ignore_index=True)

## Now, lets spit the dataframe into groups by-measurements.
grouped_dfs_02 = []
for group in reshaped_dataset.groupby('measurement'):
    grouped_dfs_02.append(group[1])

## make the box plot of several measured variables, compared between species
plt.figure(figsize=(20, 5), dpi=80)
plt.suptitle('Distribution of floral traits in the species of iris')

sp_name = ['Iris-setosa', 'Iris-versicolor', 'Iris-virginica']
setosa = mpatches.Patch(color='red')
versi = mpatches.Patch(color='green')
virgi = mpatches.Patch(color='blue')

my_pal = {"versicolor": "g", "setosa": "r", "virginica": "b"}
plt_index = 0

# for i, df in enumerate(grouped_dfs_02):
for group_name, df in reshaped_dataset.groupby('measurement'):
    axi = plt.subplot(1, len(grouped_dfs_02), plt_index + 1)
    sp_name = ['Iris-setosa', 'Iris-versicolor', 'Iris-virginica']
    df_melt = df.melt('measurement', var_name='species', value_name='values')

    sns.boxplot(data=df_melt, x='species', y='values', ax=axi, orient="v", palette=my_pal)
    plt.title(group_name)
    plt_index += 1

# Move the legend to an empty part of the plot
plt.legend(title='species', labels=sp_name,
           handles=[setosa, versi, virgi], bbox_to_anchor=(1, 1.23),
           fancybox=True, shadow=True, ncol=5, loc='upper right')
plt.tight_layout()
plt.show()

結果圖

import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns

# load iris data
iris = sns.load_dataset("iris")

   sepal_length  sepal_width  petal_length  petal_width species
0           5.1          3.5           1.4          0.2  setosa
1           4.9          3.0           1.4          0.2  setosa
2           4.7          3.2           1.3          0.2  setosa
3           4.6          3.1           1.5          0.2  setosa
4           5.0          3.6           1.4          0.2  setosa

# create figure
fig = plt.figure(figsize=(20, 5), dpi=80)

# add subplots
for i, col in enumerate(iris.columns[:-1], 1):
    plt.subplot(1, 4, i)
    ax = sns.boxplot(x='species', y=col, data=iris, hue='species')
    ax.get_legend().remove()
    plt.title(col)

# add legend
handles, labels = ax.get_legend_handles_labels()
fig.legend(handles, labels, loc='upper right', ncol=3, bbox_to_anchor=(.75, 0.98))

# add subtitle
fig.suptitle('Distribution of floral traits in the species of iris')

plt.show()

在此處輸入圖像描述

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM