2

I want my my 21 lines of data on the same graph to be more interpretable with the Legend. For instance, perhaps I could make every other legend entry / line be displayed with dashes instead of a continuous line. My mixed use of Seaborn and Matplotlib is confusing me - I'm not sure how to get the dashes in there in an alternating way.

products = list(data_cleaned.columns)
print('products: \n',products)
for i, product in enumerate(products):
    subset = data_cleaned[data_cleaned[product]>0][product]
    sns.distplot(subset,hist=False,kde=True,kde_kws={'linewidth':3},label=product)
    if i%2 == 0:
        plt.plot(subset,'-', dashes = [8, 4, 2, 4, 2, 4])

sns.set(rc = {'figure.figsize':(25,10)})
#sns.palplot()
palette_to_use = sns.color_palette("hls", 21)
sns.set_palette(palette_to_use)
#cmap = ListedColormap(sns.color_palette().as_hex())
plt.legend(prop={'size': 16}, title = 'Product')
plt.title('Density Plot with Multiple Products')
plt.xlabel('log10 of monthly spend')
plt.ylabel('Density')

Here's my current output: enter image description here

djakubosky
  • 907
  • 8
  • 15
ColinMac
  • 620
  • 2
  • 9
  • 18

2 Answers2

1

you can provide the linestyle arg in kde_kws= {'linestyle': '--'} in distplot, as you did with linewidth- Alternate the linestyles between '-' and '--' to achieve your desired effect.

example

import numpy as np; np.random.seed(10)
import seaborn as sns; sns.set(color_codes=True)
mean, cov = [0, 2], [(1, .5), (.5, 1)]
x, y = np.random.multivariate_normal(mean, cov, size=50).T
ax = sns.distplot(x, hist = False, kde=True, kde_kws={'linestyle': '--'})
djakubosky
  • 907
  • 8
  • 15
  • This only shows how to modify one of the lines - it doesn't cycle through linestyles - so, it forces me to explicitly make each Axes. My requirement is that there could be a varying number of axes drawn. – ColinMac Apr 04 '19 at 16:33
  • 1
    I am confused by that requirement, in that your example shows a single axes, my assumption was that you'd make that ahead of time and plot each line onto it passing the sns.distplot(ax=some_ax). You may want to change the name of your question to better reflect your requirement of cycling through various linestyles, instead of alternating between solid and dashed. – djakubosky Apr 04 '19 at 20:18
  • How does your solution do any alternating? – ColinMac Apr 04 '19 at 21:35
  • 1
    Oh I assumed the confusion was passing the kwarg to seaborn for linestyles (which is sometimes not possible for certain seaborn plot elements), not the specifics of cycling- using that cycle object is a good way to go! – djakubosky Apr 04 '19 at 21:47
1

The correct way to do this is to use a cycler:

# added this:
from itertools import cycle
ls = ['-','--',':','-.','-','--',':','-.','-','--',':','-.','-','--',':','-.','-','--',':','-.','-','--',':','-.']
linecycler = cycle(ls)

products = list(data_cleaned.columns)
print('products: \n',products)
for i, product in enumerate(products):
    subset = data_cleaned[data_cleaned[product]>0][product]
    ax = sns.distplot(subset,hist=False,kde=True,kde_kws={'linewidth':3,'linestyle':next(linecycler)},label=product)
# loop through next(linecycler)

sns.set(rc = {'figure.figsize':(25,10)})
#sns.palplot()
palette_to_use = sns.color_palette("hls", 21)
sns.set_palette(palette_to_use)
#cmap = ListedColormap(sns.color_palette().as_hex())
plt.legend(prop={'size': 16}, title = 'Product')
plt.title('Density Plot with Multiple Products')
plt.xlabel('log10 of monthly spend')
plt.ylabel('Density')

Now the lines are more easily discerned

ColinMac
  • 620
  • 2
  • 9
  • 18
  • For more reference: https://matplotlib.org/tutorials/intermediate/color_cycle.html – ColinMac Apr 04 '19 at 19:27
  • 1
    Just for the benefit of everyone coming back to this >2 years later: distplot is deprecated. You can do this now with kdeplot(), which takes linestyle directly as a kwarg. – ColorOutOfSpace Feb 15 '23 at 01:21