Я действительно думал о той же проблеме некоторое время назад.Я не придумал лучших решений, но у меня есть взлом, который работает нормально.К сожалению, это гораздо проще реализовать, если вы используете dodge=True
.
Идея состоит в том, чтобы собрать PathCollections
объекты, созданные swarmplot
.Если dodge=True
, то вы получите N_cat*N_hues+N_hues
коллекций (дополнения N_hues используются для создания легенды).Вы можете просто перебрать этот список.Поскольку мы хотим, чтобы все оттенки были одинаковыми, мы используем шаг N_hues, чтобы получить все коллекции, соответствующие каждому из оттенков.После этого вы можете обновить paths
этой коллекции до любого Path
объекта, который вы выберете.Обратитесь к документации для Path
, чтобы узнать, как создавать пути.
Чтобы упростить вещи, я создал несколько фиктивных диаграмм разброса перед руками, чтобы получить несколько готовых Paths
, которые я могу использовать,Конечно, любой Path
должен быть в состоянии работать.
import seaborn as sns
import matplotlib.pyplot as plt
sns.set(style="whitegrid")
tips = sns.load_dataset("tips")
fig, ax = plt.subplots(1,1)
# 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()
ax = sns.swarmplot(x="day", y="total_bill", hue="sex",data=tips,size=8,ax=ax, dodge=True)
N_hues = len(pd.unique(tips.sex))
c = ax.collections
for a in c[::N_hues]:
a.set_paths([triangle_up_mk])
for a in c[1::N_hues]:
a.set_paths([square_mk])
#update legend
ax.legend(c[-2:],pd.unique(tips.sex))
plt.show()
![enter image description here](https://i.stack.imgur.com/9hdFq.png)
ОБНОВЛЕНИЕ Решение, которое «работает»с dodge=False
.
Если вы используете dodge=False
, вы получите N + 2 коллекции, по одной для каждой категории, +2 для легенды.Проблема в том, что в этих коллекциях перемешаны все разные цвета маркеров.
Возможное, но некрасивое решение состоит в том, чтобы перебрать каждый элемент коллекции и создать массив из Path
объектов на основе одногоцвет каждого элемента.
import seaborn as sns
import matplotlib.pyplot as plt
sns.set(style="whitegrid")
tips = sns.load_dataset("tips")
fig, ax = plt.subplots(1,1)
ax = sns.swarmplot(x="day", y="total_bill", hue="sex",data=tips,size=8,ax=ax, dodge=False)
collections = ax.collections
unique_colors = np.unique(collections[0].get_facecolors(), axis=0)
markers = [triangle_up_mk, square_mk] # this array must be at least as large as the number of unique colors
for collection in collections:
paths = []
for current_color in collection.get_facecolors():
for possible_marker,possible_color in zip(markers, unique_colors):
if np.array_equal(current_color,possible_color):
paths.append(possible_marker)
break
collection.set_paths(paths)
#update legend
ax.legend(collections[-2:],pd.unique(tips.sex))
plt.show()
![enter image description here](https://i.stack.imgur.com/1nLI7.png)