【问题标题】:Separate seaborn legend into two distinct boxes将 seaborn 传说分成两个不同的盒子
【发布时间】:2019-10-20 18:08:03
【问题描述】:

我正在使用 Seaborn 生成多种类型的图表,但这里将仅使用一个简单的示例基于包含的数据集进行说明:

import seaborn
tips = seaborn.load_dataset("tips")
axes = seaborn.scatterplot(x="day", y="tip", size="sex", hue="time", data=tips)

在这个结果中,单个图例框包含两个标题“时间”和“性别”,每个标题都有子元素。

如何轻松地将图例分成两个框,每个框都有一个标题? IE。一个用于指示颜色代码的图例框(可以放在左侧),一个用于指示尺寸代码的图例框(可以放在右侧)。

【问题讨论】:

    标签: python matplotlib seaborn legend


    【解决方案1】:

    以下代码运行良好,因为时间类别的数量与性别类别的数量相同。如果不一定是这样,则必须先验计算每个“标签”需要多少行图例

    fig = plt.figure()
    tips = seaborn.load_dataset("tips")
    axes = seaborn.scatterplot(x="day", y="tip", size="sex", hue="time", data=tips)
    h,l = axes.get_legend_handles_labels()
    l1 = axes.legend(h[:int(len(h)/2)],l[:int(len(l)/2)], loc='upper left')
    l2 = axes.legend(h[int(len(h)/2):],l[int(len(l)/2):], loc='upper right')
    axes.add_artist(l1) # we need this because the 2nd call to legend() erases the first
    

    【讨论】:

      【解决方案2】:

      如果你想用 matplotlib 代替 seaborn,

      import matplotlib.pyplot as plt
      import seaborn
      tips = seaborn.load_dataset("tips")
      
      tips["time_int"] = tips["time"].cat.codes
      tips["sex_int"] = (tips["sex"].cat.codes*5+5)**2
      
      sc = plt.scatter(x="day", y="tip", s="sex_int", c="time_int", data = tips, cmap="bwr")
      
      leg1 = plt.legend(sc.legend_elements("colors")[0], tips["time"].cat.categories,
                        title="Time", loc="upper right")
      leg2 = plt.legend(sc.legend_elements("sizes")[0], tips["sex"].cat.categories,
                        title="Sex", loc="upper left")
      plt.gca().add_artist(leg1)
      plt.show()
      

      【讨论】:

        【解决方案3】:

        我接受了Diziet's answer 并对其进行了扩展。他生成了我需要的必要语法,但正如他所指出的,缺少一种方法来计算拆分图例需要多少行图例。我已经添加了这个,并写了一个完整的脚本:

        # Modules #
        import seaborn
        from matplotlib import pyplot
        
        # Plot #
        tips = seaborn.load_dataset("tips")
        axes = seaborn.scatterplot(x="day", y="tip", size="sex", hue="time", data=tips)
        
        # Legend split and place outside #
        num_of_colors   = len(tips['time'].unique()) + 1
        handles, labels = axes.get_legend_handles_labels()
        color_hl = handles[:num_of_colors], labels[:num_of_colors]
        sizes_hl = handles[num_of_colors:], labels[num_of_colors:]
        
        # Call legend twice #
        color_leg = axes.legend(*color_hl,
                                bbox_to_anchor = (1.05, 1),
                                loc            = 'upper left',
                                borderaxespad  = 0.)
        sizes_leg = axes.legend(*sizes_hl,
                                bbox_to_anchor = (1.05, 0),
                                loc            = 'lower left',
                                borderaxespad  = 0.)
        
        # We need this because the 2nd call to legend() erases the first #
        axes.add_artist(color_leg)
        
        # Adjust #
        pyplot.subplots_adjust(right=0.75)
        
        # Display #
        pyplot.ion()
        pyplot.show()
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2019-06-18
          • 2018-06-12
          • 2021-08-31
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2019-07-13
          • 2017-07-04
          相关资源
          最近更新 更多