seabornlinestyle

Not able to change linestyle in Seaborn plot


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:

enter image description here

Why I am not able to change linestyle in this code?


Solution

  • 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()
    

    sns.pointplot with line styles