【问题标题】:How can you edit multiple legend boxes in a seanborn scatter plot?如何在 seaborn 散点图中编辑多个图例框?
【发布时间】:2021-10-28 18:12:52
【问题描述】:

我想重命名和移动这两个图例。我希望顶部图例位于图表之外,右上角,标题为'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()

【问题讨论】:

    标签: python matplotlib plot seaborn legend


    【解决方案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
    

    最后可以去掉seaborn绘制的图例,画出你想要的两个图例:

    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()
    

    【讨论】:

    • 这是完美的。谢谢!
    猜你喜欢
    • 2020-06-06
    • 1970-01-01
    • 2019-04-15
    • 2021-07-11
    • 2020-11-07
    • 2020-12-04
    • 2021-02-20
    • 2019-05-13
    • 2020-07-03
    相关资源
    最近更新 更多