I have a dataframe modified from iris dataset where there is 1 numeric and 2 categorical columns:
PL Species group
4.400 versicolor A
1.600 setosa B
5.600 virginica A
4.700 versicolor B
6.100 virginica B
I want to plot a seaborn lineplot with lines in black color and with different linestyle for each Species. I tried following codes:
sns.pointplot(data=rnegdf, x='group', y='PL', hue='Species',
color='k', style='Species'); plt.show()
sns.pointplot(data=rnegdf, x='group', y='PL', hue='Species',
color='k', hue_kws=dict(ls=['-','-.','.'])); plt.show()
sns.pointplot(data=rnegdf, x='group', y='PL', hue='Species',
color='k', linestyle='Species'); plt.show()
sns.pointplot(data=rnegdf, x='group', y='PL', hue='Species',
color='k', linestyle='Species', style='Species'); plt.show()
sns.pointplot(data=rnegdf, x='group', y='PL', hue='Species',
color='k', linestyle='Species', style='Species', dashes='Species'); plt.show()
However, they all plot solid lines only:
Why I am not able to change linestyle in this code?
According to the sns.pointplot()
docs, linestyles=
(plural) can provide a line style for each of the hue values.
Note that the linestyle isn't (yet) shown in the legend. See e.g. issue 2005 or Seaborn setting line style as legend. The suggested workaround is to also set different markers, which do show up in the legend. Or to create legend handles via ax.get_lines()
.
The following way to create the legend would need some adaption if more elements would be plotted into the same subplot:
from matplotlib import pyplot as plt
import seaborn as sns
import pandas as pd
from io import StringIO
df_str = ''' PL Species group
4.400 versicolor A
1.600 setosa B
1.600 setosa A
5.600 virginica A
4.700 versicolor B
6.100 virginica B'''
rnegdf = pd.read_csv(StringIO(df_str), delim_whitespace=True)
ax = sns.pointplot(data=rnegdf, x='group', y='PL', hue='Species', color='k',
linestyles=['-', '-.', ':'])
point_handles, labels = ax.get_legend_handles_labels()
ax.legend(handles=[(line_hand, point_hand) for line_hand, point_hand in zip(ax.lines[::3], point_handles)],
labels=labels, title=ax.legend_.get_title().get_text(), handlelength=3)
plt.show()