如何在 Seaborn 散点图图例中组合色调和样式组?

How can I combine hue and style groups in a Seaborn scatter plot legend?

我已经遵循了这个问题中的代码:

我想更改图例,使样式和色调不是单独的列表,而是实际上组合在一起。

#practice dataset before applying to above
df = pd.DataFrame({"Sites" : ["Site 1","Site 1", "Site 2", "Site 2", "Site 3", "Site 3"],
                   "Depth" : ["a" , "b", "c", "d", "e", "f"],
                   "D/L_FAA" : [0.1 , 0.2, 0.3, 0.4, 0.5, 0.6],
                   "D/L_THAA" : [0.1 , 0.2, 0.3, 0.4, 0.5, 0.6]})

#creating dictionary for legend

dictionary = df.set_index("Depth")["Sites"].to_dict()
df['Subscale'] = df['Depth'].apply(lambda i: dictionary[i])
df['Subscale'] = pd.Categorical(df['Subscale'])  # creates a fixed order


#create plot
ax = sns.scatterplot(data = df, x = "D/L_FAA", y = "D/L_THAA", style = "Depth", 
                     hue = "Subscale", palette="colorblind", markers=True)
# create a dictionary mapping the subscales to their color
handles, labels = ax.get_legend_handles_labels()
index_depth_title = labels.index('Depth')
color_dict = {label: handles.get_color()
              for handle, label in zip(handles[1:index_depth_title], labels[1:index_depth_title])}

# loop through the items, assign color via the subscale of the item idem
for handle, label in zip(handles[index_depth_title + 1:], labels[index_depth_title + 1:]):
   handle.set_color(color_dict[dictionary[handle]])

# create a legend only using the items
ax.legend(handles[index_depth_title + 1:], labels[index_depth_title + 1:], title='Item',
          bbox_to_anchor=(1.03, 1.02), fontsize=10)

plt.tight_layout()
plt.show()

我目前收到此错误:

AttributeError: 'list' object has no attribute 'get_color'

我不确定为什么我的代码无法正常工作,而问题中的代码可以正常工作。

如有任何帮助,我们将不胜感激。

谢谢,

艾莉

下面的代码做了如下改动:

  • 将变量 dictionary 重命名为 depth_to_site_dict
  • in color_dict = {label: handles.get_color() ...}:将handles更改为handle,将get_color更改为get_facecolor()(链接图使用了线图,在此代码中我们有散点图)
  • handle.set_color(color_dict[dictionary[handle]])中:使用color_dict[depth_to_site_dict[label]]
from matplotlib import pyplot as plt
import seaborn as sns
import pandas as pd
import numpy as np

df = pd.DataFrame({"Sites": ["Site 1", "Site 1", "Site 2", "Site 2", "Site 3", "Site 3"],
                   "Depth": ["a", "b", "c", "d", "e", "f"],
                   "D/L_FAA": [0.1, 0.2, 0.3, 0.4, 0.5, 0.6],
                   "D/L_THAA": [0.1, 0.2, 0.3, 0.4, 0.5, 0.6]})
# creating dictionary for legend
depth_to_site_dict = df.set_index("Depth")["Sites"].to_dict()
df['Subscale'] = df['Depth'].map(depth_to_site_dict)
df['Subscale'] = pd.Categorical(df['Subscale'])  # creates a fixed order

# create plot
ax = sns.scatterplot(data=df, x="D/L_FAA", y="D/L_THAA", style="Depth",
                     hue="Subscale", palette="colorblind", markers=True)
# create a dictionary mapping the subscales to their color
handles, labels = ax.get_legend_handles_labels()
index_depth_title = labels.index('Depth')
color_dict = {label: handle.get_facecolor()
              for handle, label in zip(handles[1:index_depth_title], labels[1:index_depth_title])}

# loop through the items, assign color via the subscale of the item idem
for handle, label in zip(handles[index_depth_title + 1:], labels[index_depth_title + 1:]):
    handle.set_color(color_dict[depth_to_site_dict[label]])

# create a legend only using the items
ax.legend(handles[index_depth_title + 1:], labels[index_depth_title + 1:], title='Item',
          bbox_to_anchor=(1.03, 1.02), fontsize=10)

plt.tight_layout()
plt.show()