user2822693
user2822693

Reputation: 1330

Different markers for each hue in lmplot seaborn

How do you set-up your lmplot such that not only you have a different hue for each variable, but a different marker too?

For example, how would you get a different marker for these points, based on which 'category' they belong in?

import pandas as pd
import seaborn as sns
dic={"A":[4,6,5], "B":[2,7,5], "category":['A','A',"B"]}
df=pd.DataFrame(dic)
sns.lmplot('A', 'B', data=df, hue='category', fit_reg=False)]

I have been trying to pass in a list iter, such as :

marker_cycle=['o', 'x', '^']
[next(marker_cycle) for i in df["category"].unique()

but have not been successful.

Upvotes: 3

Views: 15710

Answers (4)

Onyr
Onyr

Reputation: 915

To complete the response by @ImportanceOfBeingErnest here is what you can use. I checked the source code of matplotlib, used by seaborn to get most of the options. I made this response for others like me wanting to also have different line styles, and more options for markers.

Here is what I did to draw a graph with wide range of line and marker styles (Note that in my example, "category" is "team"):

import itertools

# marker : str, default: 'o' circle marker
# marker style available: ['o','.', ',', 'v', '^', '<', '>', '1', '2', '3', '4', '8', 's', 'p', 'P', '*', 'h', 'H', '+', 'x', 'X', 'D', 'd', '|', '_']
marker = itertools.cycle(['o', '^', '*', '8', 's', 'p', 'd', 'v'])
markers = [next(marker) for i in df["team"].unique()]

# line : str, default: '-' solid line style
# line style available: ['-', '--', '-.', ':', 'None', ' ', '', 'solid', 'dashed', 'dashdot', 'dotted']
line = itertools.cycle(['-', '--', '-.', ':', 'solid', 'dashed', 'dashdot', 'dotted'])
lines = [next(line) for i in df["team"].unique()]

# plot graph
g2 = sns.catplot(
    data=df, 
    x="day", 
    y="commits", 
    hue="team", 
    kind="point",
    markers=markers,
    linestyles=lines,
    aspect=1.5
)

Which gives: enter image description here

Side note

Available options inside _axes.py of matplotlib.axes:

**Markers**

        =============   ===============================
        character       description
        =============   ===============================
        ``'.'``         point marker
        ``','``         pixel marker
        ``'o'``         circle marker
        ``'v'``         triangle_down marker
        ``'^'``         triangle_up marker
        ``'<'``         triangle_left marker
        ``'>'``         triangle_right marker
        ``'1'``         tri_down marker
        ``'2'``         tri_up marker
        ``'3'``         tri_left marker
        ``'4'``         tri_right marker
        ``'8'``         octagon marker
        ``'s'``         square marker
        ``'p'``         pentagon marker
        ``'P'``         plus (filled) marker
        ``'*'``         star marker
        ``'h'``         hexagon1 marker
        ``'H'``         hexagon2 marker
        ``'+'``         plus marker
        ``'x'``         x marker
        ``'X'``         x (filled) marker
        ``'D'``         diamond marker
        ``'d'``         thin_diamond marker
        ``'|'``         vline marker
        ``'_'``         hline marker
        =============   ===============================

        **Line Styles**

        =============    ===============================
        character        description
        =============    ===============================
        ``'-'``          solid line style
        ``'--'``         dashed line style
        ``'-.'``         dash-dot line style
        ``':'``          dotted line style
        =============    ===============================

Upvotes: 0

tratwa
tratwa

Reputation: 1

Maybe adding style='category'

sns.lmplot('A', 'B', data=df, hue='category', style='category', fit_reg=False)]

Upvotes: -1

ImportanceOfBeingErnest
ImportanceOfBeingErnest

Reputation: 339052

See this issue. next() needs to work with an iterator. You could create one with intertools,

import itertools
mks = itertools.cycle(['o', 'x', '^', '+', '*', '8', 's', 'p', 'D', 'V'])
markers = [next(mks) for i in df["category"].unique()]

Example:

import pandas as pd
import seaborn as sns
import matplotlib.pyplot as plt

dic={"A":[4,6,5], "B":[2,7,5], "category":['A','A',"B"]}
df=pd.DataFrame(dic)

import itertools
mks = itertools.cycle(['o', 'x', '^', '+', '*', '8', 's', 'p', 'D', 'V'])
markers = [next(mks) for i in df["category"].unique()]

sns.lmplot('A', 'B', data=df, hue='category', markers=markers, fit_reg=False)

plt.show()

Note that this may be a bit overkill and you can simply get the markers fromt the list directly,

marker = ['o', 'x', '^', '+', '*', '8', 's', 'p', 'D', 'V']
markers = [marker[i] for i in range(len(df["category"].unique()))]

Complete example:

import pandas as pd
import seaborn as sns
import matplotlib.pyplot as plt

dic={"A":[4,6,5], "B":[2,7,5], "category":['A','A',"B"]}
df=pd.DataFrame(dic)

marker = ['o', 'x', '^', '+', '*', '8', 's', 'p', 'D', 'V']
markers = [marker[i] for i in range(len(df["category"].unique()))]

sns.lmplot('A', 'B', data=df, hue='category', markers=markers, fit_reg=False)

plt.show()

Both solutions from above result in the same plot:

enter image description here

Upvotes: 3

BENY
BENY

Reputation: 323226

There is markers inside the sns.lmplot

sns.lmplot('A', 'B', data=df, hue='category', fit_reg=False,markers=['o', 'x'])

enter image description here

Upvotes: 4

Related Questions