【问题标题】:Change axis along which Seaborn applies color palette更改 Seaborn 应用调色板的轴
【发布时间】:2019-12-27 07:05:03
【问题描述】:

我正在尝试使用 Seaborn 将一维数据框呈现为水平条形图。我想使用冷暖调色板对条形进行着色以反映它们的大小和方向。

换句话说,我希望生成类似于此处显示的第二个示例的内容(来自Seaborn site),但我想将其水平定向:

我已经成功地将图表横向翻转,但我似乎无法使调色板也沿水平轴应用。我的代码:

import pandas as pd, seaborn as sns

sns.set()
df = pd.DataFrame([7,-5,-2,1.5,-3],
                  index=['question 1','question 2','question 3','question 4','question 5'],
                  columns=['t'])
sns.barplot(data=    df,
            x=       't', 
            y=       df.index,
            palette= 'coolwarm') 

输出:

当你从左到右(而不是从上到下)移动时,我希望它从蓝色变为红色。

【问题讨论】:

    标签: python pandas seaborn


    【解决方案1】:

    如果您不介意问题按价值递增的顺序排列,您可以执行以下操作:

    df2 = df.sort_values('t')
    
    sns.barplot(data=df2,
                x='t',
                y=df2.index
                palette='coolwarm_r')
    

    应该产生的结果:

    如果您想按原始顺序保留问题,可以使用 palette kwarg 为 sns.barplot 指定自定义调色板(RGBA 值列表):

    val_order = df['t'].rank(method='max').astype(int) # rank ordered values in column 't'
    val_index = val_order - 1 # convert for use as a list index
    colors = sns.color_palette('coolwarm_r', len(df.index)) # list of N colors spaced along coolwarm
    palette = [colors[x] for x in val_index] # re-order colors with increasing value of 't'
    
    sns.barplot(data=df, x='t', y=df.index, palette=palette)
    

    产量:

    制作图像后,我意识到我不小心使用了coolwarm_r 而不是coolwarm。添加_r 后缀将使用反转的颜色图。哦,好吧。

    【讨论】:

    • 谢谢!然而,在这两种解决方案中,颜色的深浅似乎对应于项目在排序中的位置,而不是它的实际大小。由于我的实际数据并非如此均匀分布,因此我想让颜色的深浅反映它们的大小(例如,问题 3 和 4 都应该或多或少地显示为灰色)。
    • 第二个选项根据't'列中的值选择颜色。您也可以使用数据框中的任何其他列,例如分配一个幅度列,并使用它来选择颜色:df.assign(magnitude=lambda x: abs(x['t']))
    • 你确定吗?在玩了一些之后,它看起来真的是根据 ranked t 值而不是 t 值本身来选择颜色。请注意,colors = sns.color_palette('coolwarm_r', len(df.index)) 行会生成一个 均匀间隔 颜色列表,然后在下一行中将这些颜色按列表分配给调色板。
    • 我明白你的意思。你是对的。在这种情况下,我认为您可以使用matplotlib colormap 生成传递给palette kwarg 的RGBA 值。另见colormap normalization
    【解决方案2】:

    Seaborn 不执行任何真正的颜色映射。因此,如果需要这样做,则需要在外部进行。在下文中,每个条形图根据其大小从颜色图中获取其颜色。

    import matplotlib.pyplot as plt
    import numpy as np
    import pandas as pd
    import seaborn as sns
    
    sns.set()
    df = pd.DataFrame([7,-5,-2,1.5,-3],
                      index=['question 1','question 2','question 3','question 4','question 5'],
                      columns=['t'])
    
    absmax = np.abs(df["t"].values).max()
    norm = plt.Normalize(-absmax, absmax)
    cmap = plt.get_cmap("coolwarm")
    colors = cmap(norm(df["t"].values))
    plt.barh("index", "t", data=df.reset_index(), color=colors)
    
    plt.colorbar(plt.cm.ScalarMappable(norm, cmap))
    
    plt.gca().invert_yaxis()
    plt.tight_layout()
    plt.show()
    

    【讨论】:

    • 这正是我想要的。感谢您的回复。
    【解决方案3】:

    这将是一个非常晚的回复,但是......

    最简单的方法是将hue 参数设置为您希望设置为着色轴的列:

    sns.barplot(data=df,x='t',y=df.index,palette='coolwarm', hue='t', dodge=False)
    

    dodge 设置为True 至关重要,否则您会得到非常细的线状框。

    你会得到这样的输出:

    Output

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-12-16
      • 1970-01-01
      • 1970-01-01
      • 2020-04-28
      • 2016-07-10
      相关资源
      最近更新 更多