Вот как я мог это сделать. Вам необходимо использовать столбец cat
для управления различными параметрами графика (цвет, стиль, размер маркера), а затем создавать объекты отображения (здесь дикты), которые сообщают, какое значение параметра использовать для каждой категории. Цвет легкий. Стиль линий сложнее, потому что Seaborn предлагает только dashes
в качестве настраиваемого параметра, который должен быть задан в расширенном формате Matplotlib (segment, gap)
. Функция matplotlib.lines._get_dash_pattern
переводит строковое значение (например, --
) в этот формат, хотя возвращаемое значение необходимо обрабатывать с осторожностью. К сожалению, для размера маркера lineplot
не дает возможности изменить размер маркера в зависимости от категории (даже если вы можете изменить стиль маркера), поэтому вам нужно использовать scatterplot
сверху. Последний бит - это легенда, вы, вероятно, захотите отключить ее для второго сюжета, чтобы не повторять ее, но проблема в том, что у первой легенды не будет маркеров. Если это вас беспокоит, вы все равно можете редактировать легенду вручную. В общем, это может выглядеть так:
import pandas as pd
import matplotlib as mpl
import matplotlib.pyplot as plt
import seaborn as sns
# Converts a line style to a format acceptable by Seaborn
def get_dash_pattern(style):
_, dash = mpl.lines._get_dash_pattern(style)
return dash if dash else (None, None)
data_tmp = pd.DataFrame({
'x': [0,14,28,42,56, 0,14,28,42,56],
'y': [0, 0.003, 0.006, 0.008, 0.001, 0*2, 0.003*2, 0.006*2, 0.008*2, 0.001*2],
'cat': ['A','A','A','A','A','B','B','B','B','B'],
'color': ['#B5D8F0','#B5D8F0','#B5D8F0','#B5D8F0','#B5D8F0',
'#247AB2','#247AB2','#247AB2','#247AB2','#247AB2'],
'point': [14,14,14,14,14,28,28,28,28,28],
'linestyles':['-','-','-','-','-','--','--','--','--','--']})
# Extract plot features as dicts
feats = (data_tmp[['cat', 'color', 'linestyles', 'point']]
.set_index('cat').drop_duplicates().to_dict())
palette, dashes, sizes = feats['color'], feats['linestyles'], feats['point']
# Convert line styles to dashes
dashes = {k: get_dash_pattern(v) for k, v in dashes.items()}
# Lines
lines = sns.lineplot(x="x", y="y", hue="cat", style="cat", data=data_tmp,
palette=palette, dashes=dashes)
# Points
sns.scatterplot(x="x", y="y", hue="cat", size="cat", data=data_tmp,
palette=palette, sizes=sizes, legend=False)
# Fix legend
for t, l in zip(lines.legend().get_texts(), lines.legend().get_lines()):
l.set_marker('o')
l.set_markersize(sizes.get(l.get_label(), 0) / t.get_fontsize())
plt.show()
Вывод: