如何在 Seaborn 的线图中为特定的线条应用线型?

4

我有一个数据框,其中在产品列中有许多不同的项目,让我们只显示一些:

import numpy as np
import pandas as pd
import seaborn as sns
import matplotlib.pyplot as plt

data = np.array([[1, 1, 570], [2, 1, 650], [1, 2, 27], [2, 2, 64], [1, 3, 125], [2, 3, 216],  
                  [1, 'item_1', 343], [2, 'item_1', 340], [1, 'item_2', 343], [2, 'item_2', 345]])
df = pd.DataFrame(data=data, columns=["Flag", "Products", "Value"])

我正在使用Seaborn获取以下线图:

sns.set_theme()
sns.set_style("ticks")
sns.set_context("paper")

fig1, ax1 = plt.subplots()
sns.lineplot(data=df, x="Flag", y="Value", 
             hue="Products", style="Products", ax=ax1)
plt.legend(bbox_to_anchor=(1.02, 1),borderaxespad=0)
fig1.tight_layout()

通过这种方式,所有的线条都使用Seaborn选择的样式,但是我需要为名称为“item_1”和“item_2”的产品设置特定的颜色和线条样式(而不是虚线)。 到目前为止,我找到了以下解决方案:

palette = {c:'red' if c=='item_1' else 'blue' for c in df.Products.unique()}
sns.lineplot(data=df, x="Flag", y="Value", 
             hue="Products", style="Products", palette=palette, ax=ax1)

因此,我只能将红色设置为item_1,但所有其他行都是蓝色的,而我想要:

  • 为item_1和item_2同时设置红色和非虚线
  • 为所有其他行设置另一个颜色调色板(例如明亮)

这是否有可能?

2个回答

10

palette=dashes=可以传递一个将所使用列的级别映射到不同颜色/样式的字典。

您可以手动或程序化地生成这些字典(取决于您有多少级别)。

例如,颜色调色板:

#color palette
cmap = sns.color_palette("bright")
palette = {key:value for key,value in zip(data[hue_col].unique(), cmap)}
palette['item_1'] = 'red'
palette['item_2'] = 'red'

输出:

{'1': (0.00784313725490196, 0.24313725490196078, 1.0),
'2': (1.0, 0.48627450980392156, 0.0),
'3': (0.10196078431372549, 0.788235294117647, 0.2196078431372549),
'item_1': 'red,
'item_2': 'red'}
我们从“亮色”调色板中为每个级别分配不同的颜色,并且如果需要,我们可以手动固定一些值(尽管请记住,“亮色”调色板中已经有一种非常类似于红色的颜色,因此可能存在某些可能的混淆)。
对于虚线样式,也可以使用同样的方法实现。
#style palette
dash_list = sns._core.unique_dashes(data[style_col].unique().size+1)
style = {key:value for key,value in zip(data[style_col].unique(), dash_list[1:])}
style['item_1'] = ''  # empty string means solid
style['item_2'] = ''

输出:

{'1': (4, 1.5),
'2': (1, 1),
'3': (3, 1.25, 1.5, 1.25),
'item_1': '',
'item_2': ''}

这里我使用了seaborn的一个私有函数(自行承担风险,可能随时更改)来生成虚线样式列表,然后手动设置我想要用实线的特定级别。我在dash_list中请求了一个多余的项目,因为第一个元素总是实线,我希望保留实线给item_1item_2

完整代码:

data = df
x_col = 'Flag'
y_col = "Value"
hue_col = "Products"
style_col = "Products"

#color palette
cmap = sns.color_palette("bright")
palette = {key:value for key,value in zip(data[hue_col].unique(), cmap)}
palette['item_1'] = 'red'
palette['item_2'] = 'red'


#style palette
dash_list = sns._core.unique_dashes(data[style_col].unique().size+1)
style = {key:value for key,value in zip(data[style_col].unique(), dash_list[1:])}
style['item_1'] = ''  # empty string means solid
style['item_2'] = ''

sns.set_theme()
sns.set_style("ticks")
sns.set_context("paper")

fig1, ax1 = plt.subplots()
sns.lineplot(data=df, x=x_col, y=y_col, 
             hue=hue_col, palette=palette,
             style=style_col, dashes=style,
             ax=ax1)
plt.legend(bbox_to_anchor=(1.02, 1),borderaxespad=0)
fig1.tight_layout()

enter image description here


非常感谢@Diziet Asahi,这确实在示例数据框中起作用!但是,在包含许多其他项的完整数据框中,我收到错误消息:调色板字典缺少键:{'9','20',...}。那么,我该如何处理此错误?请考虑我必须分析不同数量项目的数据框。此外,是否有一种方法可以将线条样式设置为所有名为“item_x”的项目,而不是输入每个项目的名称? - heartbit

0
非常感谢 @Diziet Asahi,确实这在示例数据框中有效!但是,在我的完整数据框中,我收到错误消息:

调色板字典缺少键:{'9','20',...}

我猜这是因为seaborn中默认的颜色调色板仅使用了十种不同的色调。为了处理这个错误,我设置了以下颜色调色板:
cmap = sns.color_palette("hls", 75)

这也适用于选择“husl”颜色空间。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接