Первая часть кода пытается создать MRE.
Чтобы иметь очень маленькие маркеры, можно установить цвет линии на 'none', чтобы сделать эти линии вокруг маркеров полностью невидимыми, и использовать маркер пиксель ',' . Многие маркеры рядом с одним и тем же местом можно улучшить с помощью альфа-канала. вам может потребоваться поэкспериментировать с вашими данными, чтобы выяснить, какое количество альфа дает наилучший результат. получить строки, принадлежащие ax
. Кажется, что каждый седьмой Line2D
в списке соответствует выбросам. Мы можем извлечь их Y-позиции, добавить немного дрожания и заменить их.
import matplotlib.pyplot as plt
import seaborn as sns
import numpy as np
N = 100000
x = np.where(np.random.randint(20, size=N * 6) > 0,
np.random.normal(np.repeat([30, 35], N * 3), 10, N * 6) * np.tile([1, 1.3, 1.1], N * 2),
np.random.normal(80, 5, N * 6))
y = np.tile(['A', 'B', 'C'], N * 2)
hue = np.repeat(['X', 'Y'], N * 3)
ax = sns.boxplot(y=y, x=x, hue=hue, notch=True,
showmeans=True, meanprops={"marker": ".", "markerfacecolor": "red", "markeredgecolor": "red"},
flierprops=dict(marker=',', markerfacecolor='steelblue', markeredgecolor='none', alpha=.1),
boxprops=dict(alpha=.7), width=.3)
for line in ax.get_lines()[6::7]:
# line.set_mec('purple') # to test that we have the correct Line2Ds
yoffsets = line.get_ydata()
line.set_ydata(yoffsets + np.random.uniform(-0.05, 0.05, yoffsets.size))