如何在箱线图具有色调时自定义seaborn箱线图的特定颜色顺序

huangapple go评论60阅读模式
英文:

How to customize seaborn boxplot with specific color sequence when boxplots have hue

问题

我想制作带有色调的箱线图,但我希望对其进行颜色编码,以便每个特定的 X 字符串都有特定的颜色,而色调只是一个较浅的颜色。我可以制作不带色调的箱线图。当我加入色调时,我得到了第二个箱线图,其中失去了颜色。有人可以帮助我自定义包含色调的图的颜色吗?

基本上,这就是 这个问题 的答案,但是针对箱线图。

这是我的代码:
第一个箱线图

order=['Ash1','E1A','FUS','p53']
colors=['gold','teal','darkorange','royalblue']
color_dict=dict(zip(order,colors))
fig,ax=plt.subplots(figsize=(25,15))
bp=sns.boxplot(data=df_idrs, x=df_idrs["construct"], y=df_idrs['Norm_Ef_IDR/Ef_GS'],ax=ax,palette=color_dict)
sns.stripplot(ax=ax,y='Norm_Ef_IDR/Ef_GS', x='construct', data=df_idrs,palette=color_dict, 
                      jitter=1, marker='o', alpha=0.4,edgecolor='black',linewidth=1, dodge=True)
ax.axhline(y=1,linestyle="--",color='black',linewidth=2)
plt.legend(loc='upper left', bbox_to_anchor=(1.03, 1))

第二个箱线图

order=['Ash1','E1A','FUS','p53']
colors=['gold','teal','darkorange','royalblue']
color_dict=dict(zip(order,colors))
fig,ax=plt.subplots(figsize=(25,15))
bp=sns.boxplot(data=df_idrs, x=df_idrs["construct"], y=df_idrs['Norm_Ef_IDR/Ef_GS'],ax=ax, hue=df_idrs["location"])
sns.stripplot(y='Norm_Ef_IDR/Ef_GS', x='construct', data=df_idrs, hue=df_idrs["location"], 
                      jitter=1, marker='o', alpha=0.4,edgecolor='black',linewidth=1, dodge=True)
ax.axhline(y=1,linestyle="--",color='black',linewidth=2)
plt.legend(loc='upper left', bbox_to_anchor=(1.03, 1))

唯一改变的是调色板改为了色调。我在这里看到了许多示例,但我无法让它们起作用。使用第二个代码,我尝试了以下操作:
对于这个,什么都没有发生。

for ind, bp in enumerate(ax.findobj(PolyCollection)):
    rgb = to_rgb(colors[ind // 2])
    if ind % 2 != 0:
        rgb = 0.5 + 0.5 * np.array(rgb)  # 变成浅色
    bp.set_facecolor(rgb)

对于以下一个,我得到了索引超出范围的错误。

for i in range(0,4):
    mybox = bp.artists[i]
    mybox.set_facecolor(color_dict[order[i]])
英文:

I want to make boxplots with hues but I want to color code it so that each specific X string is a certain color with the hue just being a lighter color. I am able to do a boxplot without a hue. When I incorporate the hue, I get the second boxplot which loses the colors. Can someone help me customize the colors for the figure that contains the hue?

Essentially, its what the answer for this question is but with boxplots.

This is my code:
first boxplot

order=['Ash1','E1A','FUS','p53']
colors=['gold','teal','darkorange','royalblue']
color_dict=dict(zip(order,colors))
fig,ax=plt.subplots(figsize=(25,15))
bp=sns.boxplot(data=df_idrs, x=df_idrs["construct"], y=df_idrs['Norm_Ef_IDR/Ef_GS'],ax=ax,palette=color_dict)
sns.stripplot(ax=ax,y='Norm_Ef_IDR/Ef_GS', x='construct', data=df_idrs,palette=color_dict, 
                      jitter=1, marker='o', alpha=0.4,edgecolor='black',linewidth=1, dodge=True)
ax.axhline(y=1,linestyle="--",color='black',linewidth=2)
plt.legend(loc='upper left', bbox_to_anchor=(1.03, 1))

second boxplot

order=['Ash1','E1A','FUS','p53']
colors=['gold','teal','darkorange','royalblue']
color_dict=dict(zip(order,colors))
fig,ax=plt.subplots(figsize=(25,15))
bp=sns.boxplot(data=df_idrs, x=df_idrs["construct"], y=df_idrs['Norm_Ef_IDR/Ef_GS'],ax=ax, hue=df_idrs["location"])
sns.stripplot(y='Norm_Ef_IDR/Ef_GS', x='construct', data=df_idrs, hue=df_idrs["location"], 
                      jitter=1, marker='o', alpha=0.4,edgecolor='black',linewidth=1, dodge=True)
ax.axhline(y=1,linestyle="--",color='black',linewidth=2)
plt.legend(loc='upper left', bbox_to_anchor=(1.03, 1))

The only thing that changed was the palette to hue. I have seen many examples on here but I am unable to get them to work. Using the second code, I have tried the following:
Nothing happens for this one.

for ind, bp in enumerate(ax.findobj(PolyCollection)):
    rgb = to_rgb(colors[ind // 2])
    if ind % 2 != 0:
        rgb = 0.5 + 0.5 * np.array(rgb)  # make whiter
    bp.set_facecolor(rgb)

I get index out of range for the following one.

for i in range(0,4):
    mybox = bp.artists[i]
    mybox.set_facecolor(color_dict[order[i]]) 

答案1

得分: 0

Matplotlib 将框存储在 ax.patches 中,但还有两个虚拟补丁(用于构建图例)需要被过滤掉。stripplot 的点存储在 ax.collections 中。还有两个虚拟集合用于图例,但由于它们出现在最后,所以不构成问题。

一些备注:

  • sns.boxplot 返回它绘制的子图;因为它使用 ax=ax 被调用,它将返回相同的 ax
  • stripplot 中设置 jitter=1 会将点模糊到一个宽度为 1 的范围内。1 是 x 位置之间的距离,而框只有 0.4 宽。为避免混乱,下面的代码使用 jitter=0.4

以下是从虚拟测试数据开始的示例代码:

from matplotlib import pyplot as plt
from matplotlib.legend_handler import HandlerTuple
from matplotlib.patches import PathPatch
from matplotlib.colors import to_rgb
import seaborn as sns
import pandas as pd
import numpy as np

np.random.seed(20230215)
order = ['Ash1', 'E1A', 'FUS', 'p53']
colors = ['gold', 'teal', 'darkorange', 'royalblue']
hue_order = ['A', 'B']

df_idrs = pd.DataFrame({'construct': np.repeat(order, 200),
                        'Norm_Ef_IDR/Ef_GS': (np.random.normal(0.03, 1, 800).cumsum() + 10) / 15,
                        'location': np.tile(np.repeat(hue_order, 100), 4)})
fig, ax = plt.subplots(figsize=(12, 5))

sns.boxplot(data=df_idrs, x=df_idrs['construct'], y=df_idrs['Norm_Ef_IDR/Ef_GS'], hue='location',
            order=order, hue_order=hue_order, ax=ax)
box_colors = [f + (1 - f) * np.array(to_rgb(c))  # 根据色调变白颜色
              for c in colors for f in np.linspace(0, 0.5, len(hue_order))]
box_patches = 

for patch, color in zip(box_patches, box_colors): patch.set_facecolor(color) sns.stripplot(y='Norm_Ef_IDR/Ef_GS', x='construct', data=df_idrs, hue=df_idrs['location'], jitter=0.4, marker='o', alpha=0.4, edgecolor='black', linewidth=1, dodge=True, ax=ax) for collection, color in zip(ax.collections, box_colors): collection.set_facecolor(color) ax.axhline(y=1, linestyle='--', color='black', linewidth=2) handles = [tuple(box_patches[i::len(hue_order)]) for i in range(len(hue_order))] ax.legend(handles=handles, labels=hue_order, title='hue category', handlelength=4, handler_map={tuple: HandlerTuple(ndivide=None, pad=0)}, loc='upper left', bbox_to_anchor=(1.01, 1)) plt.tight_layout() plt.show()

如何在箱线图具有色调时自定义seaborn箱线图的特定颜色顺序

英文:

Matplotlib stores the boxes in ax.patches, but there are also 2 dummy patches (used to construct the legend) that need to be filtered away. The dots of the stripplot are stored in ax.collections. There are also 2 dummy collections for the legend, but as those come at the end, they don't form a problem.

Some remarks:

  • sns.boxplot returns the subplot on which it was drawn; as it is called with ax=ax it will return that same ax
  • Setting jitter=1in the stripplot will smear the dots over a width of 1. 1 is the distance between the x positions, and the boxes are only 0.4 wide. To avoid clutter, the code below uses jitter=0.4.

Here is some example code starting from dummy test data:

from matplotlib import pyplot as plt
from matplotlib.legend_handler import HandlerTuple
from matplotlib.patches import PathPatch
from matplotlib.colors import to_rgb
import seaborn as sns
import pandas as pd
import numpy as np

np.random.seed(20230215)
order = ['Ash1', 'E1A', 'FUS', 'p53']
colors = ['gold', 'teal', 'darkorange', 'royalblue']
hue_order = ['A', 'B']

df_idrs = pd.DataFrame({'construct': np.repeat(order, 200),
                        'Norm_Ef_IDR/Ef_GS': (np.random.normal(0.03, 1, 800).cumsum() + 10) / 15,
                        'location': np.tile(np.repeat(hue_order, 100), 4)})
fig, ax = plt.subplots(figsize=(12, 5))

sns.boxplot(data=df_idrs, x=df_idrs['construct'], y=df_idrs['Norm_Ef_IDR/Ef_GS'], hue='location',
            order=order, hue_order=hue_order, ax=ax)
box_colors = [f + (1 - f) * np.array(to_rgb(c))  # whiten colors depending on hue
              for c in colors for f in np.linspace(0, 0.5, len(hue_order))]
box_patches = 

for patch, color in zip(box_patches, box_colors): patch.set_facecolor(color) sns.stripplot(y='Norm_Ef_IDR/Ef_GS', x='construct', data=df_idrs, hue=df_idrs['location'], jitter=0.4, marker='o', alpha=0.4, edgecolor='black', linewidth=1, dodge=True, ax=ax) for collection, color in zip(ax.collections, box_colors): collection.set_facecolor(color) ax.axhline(y=1, linestyle='--', color='black', linewidth=2) handles = [tuple(box_patches[i::len(hue_order)]) for i in range(len(hue_order))] ax.legend(handles=handles, labels=hue_order, title='hue category', handlelength=4, handler_map={tuple: HandlerTuple(ndivide=None, pad=0)}, loc='upper left', bbox_to_anchor=(1.01, 1)) plt.tight_layout() plt.show()

如何在箱线图具有色调时自定义seaborn箱线图的特定颜色顺序

huangapple
  • 本文由 发表于 2023年2月16日 04:38:15
  • 转载请务必保留本文链接:https://go.coder-hub.com/75465213.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定