Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python: Changing Marker Type in Seaborn

In regular matplotlib you can specify various marker styles for plots. However, if I import seaborn, '+' and 'x' styles stop working and cause the plots not to show - others marker types e.g. 'o', 'v', and '*' work.

Simple example:

import matplotlib.pyplot as plt
import seaborn as sns

x_cross = [768]
y_cross = [1.028e8]
plt.plot(x_cross, y_cross, 'ok')

plt.gca().set_xlim([10, 1e4])
plt.gca().set_ylim([1, 1e18])
plt.xscale('log')
plt.yscale('log')

plt.show()

Produces this: Simple Seaborn Plot

Changing 'ok' on line 6 to '+k' however, no longer shows the plotted point. If I don't import seaborn it works as it should: Regular Plot With Cross Marker

Could someone please enlighten me as to how I change the marker style to a cross type when seaborn being used?

like image 558
Toby Hawkins Avatar asked Jul 14 '17 23:07

Toby Hawkins


2 Answers

The reason for this behaviour is that seaborn sets the marker edge width to zero. (see source).

As is pointed out in the seaborn known issues

An unfortunate consequence of how the matplotlib marker styles work is that line-art markers (e.g. "+") or markers with facecolor set to "none" will be invisible when the default seaborn style is in effect. This can be changed by using a different markeredgewidth (aliased to mew) either in the function call or globally in the rcParams.

This issue is telling us about it as well as this one.

In this case, the solution is to set the markeredgewidth to something larger than zero,

  • using rcParams (after importing seaborn):

    plt.rcParams["lines.markeredgewidth"] = 1
    
  • using the markeredgewidth or mew keyword argument

    plt.plot(..., mew=1)
    

However, as @mwaskom points out in the comments, there is actually more to it. In this issue it is argued that markers should be divided into two classes, bulk style markers and line art markers. This has been partially accomplished in matplotlib version 2.0 where you can obtain a "plus" as marker, using marker="P" and this marker will be visible even with markeredgewidth=0.

plt.plot(x_cross, y_cross, 'kP')

enter image description here

like image 156
ImportanceOfBeingErnest Avatar answered Sep 28 '22 07:09

ImportanceOfBeingErnest


It is very like to be a bug. However you can set marker edge line width by mew keyword to get what you want:

import matplotlib.pyplot as plt
import seaborn as sns

x_cross = [768]
y_cross = [1.028e8]

# set marker edge line width to 0.5
plt.plot(x_cross, y_cross, '+k', mew=.5)

plt.gca().set_xlim([10, 1e4])
plt.gca().set_ylim([1, 1e18])
plt.xscale('log')
plt.yscale('log')

plt.show()

enter image description here

like image 22
Serenity Avatar answered Sep 28 '22 09:09

Serenity