【问题标题】:Seaborn's boxplot+swarmplot: different color for x, different symbol for huesSeaborn 的箱线图+swarmplot:x 的颜色不同,色调的符号不同
【发布时间】:2018-10-21 04:15:43
【问题描述】:

我正在尝试使用 seaborn 和不同的x 组和额外的hues 生成箱线图。请参阅此代码:

tips = sns.load_dataset("tips")

sns.stripplot(x="day", y="total_bill", hue="smoker",
              data=tips, jitter=True,
              palette="Set2", split=True,linewidth=1,edgecolor='gray')

sns.boxplot(x="day", y="total_bill", hue="smoker",
            data=tips,palette="Set2",fliersize=0)

我希望每个 x 箱线图(在本例中为每天)具有不同的颜色,而每个 hue(在本例中为吸烟者/非吸烟者)用不同的符号表示swarmplot。

我尝试使用 palette 参数,但没有得到我想要的。我也尝试直接玩artists,但更改箱线图的facecolor 也会因某种原因更改edgecolor,而且我不知道如何更改swarmplot 上的符号。

【问题讨论】:

    标签: matplotlib boxplot seaborn


    【解决方案1】:

    我意识到,when answering this question,我从来没有为这个问题提出过自己的解决方案,即使我不久前已经一起破解了一些东西。

    # From itertools' receipes https://docs.python.org/3/library/itertools.html#itertools-recipes
    from itertools import zip_longest
    def grouper(iterable, n, fillvalue=None):
        "Collect data into fixed-length chunks or blocks"
        # grouper('ABCDEFG', 3, 'x') --> ABC DEF Gxx"
        args = [iter(iterable)] * n
        return zip_longest(*args, fillvalue=fillvalue)
    
    
    fig, ax = plt.subplots()
    # dummy plots, just to get the Path objects
    a = ax.scatter([1,2],[3,4], marker='s')
    b = ax.scatter([1,2],[3,4], marker='^')
    square_mk, = a.get_paths()
    triangle_up_mk, = b.get_paths()
    a.remove()
    b.remove()
    
    sns.swarmplot(x="day", y="total_bill", hue="smoker", data=tips, dodge=True, size=6, lw=2, edgecolor='k')
    swarm_cols = ax.collections
    
    sns.boxplot(x="day", y="total_bill", hue="smoker", data=tips, fliersize=0)
    box_cols = ax.artists
    
    ax.legend_.remove()
    
    N_cats = len(np.unique(tips.day))
    N_hues = len(np.unique(tips.smoker))
    print(N_cats,N_hues)
    
    pastels = matplotlib.cm.get_cmap('Pastel1')
    cat_colors =  [pastels(x) for x in np.linspace(0,1,N_cats)]
    hue_markers = [square_mk, triangle_up_mk]
    
    for boxes,color in zip(grouper(box_cols, N_hues),cat_colors):
        for box in boxes:
            box.set_facecolor(color)
    for swarms,color in zip(grouper(swarm_cols, N_hues), cat_colors):
        for swarm,marker in zip(swarms,hue_markers):
            print(swarm, len(swarm.get_offsets()))
            swarm.set_paths([marker])
            swarm.set_facecolors([color])
            swarm.set_linewidths([1.])
            swarm.set_edgecolors(['xkcd:dark grey'])
    
    # recreate legend
    for swarm,marker in zip(swarm_cols[-2:],hue_markers):
        print(swarm, len(swarm.get_offsets()))
        swarm.set_paths([marker])
        swarm.set_facecolors(["none"])
        swarm.set_linewidths([1.])
        swarm.set_edgecolors(['xkcd:dark grey'])
    ax.legend(swarm_cols[-2:],np.unique(tips.smoker))
    

    【讨论】:

    【解决方案2】:

    到问题的着色部分:edgecolor 和 facecolor 都可以通过艺术家单独指定。

    ax = sns.boxplot(x="day", y="total_bill", hue="smoker",
                data=tips,fliersize=0)
    
    colors = sns.color_palette('husl',n_colors=4)
    colors = sp.repeat(colors,2,axis=0)
    
    for artist,color in zip(ax.artists,colors):
        artist.set_facecolor(color)
        artist.set_edgecolor(color)
    

    对于脱衣舞情节:我也找不到如何找到制造者的方法。如果您想指定它们的颜色等,您可以通过[pc for pc in ax.get_children() if type(pc) == PathCollection] 单独获取它们......

    【讨论】:

      猜你喜欢
      • 2023-03-29
      • 2017-11-04
      • 2018-05-04
      • 1970-01-01
      • 2018-06-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-10-23
      相关资源
      最近更新 更多