No outlines on bins of Matplotlib histograms or Seaborn distplots

35,912

Solution 1

As part of the update to matplotlib 2.0 the edges on bar plots are turned off by default. However, you may use the rcParam

plt.rcParams["patch.force_edgecolor"] = True

to turn the edges on globally.

Probably the easiest option is to specifically set the edgecolor when creating a seaborn plot, using the hist_kws argument,

ax = sns.distplot(x, hist_kws=dict(edgecolor="k", linewidth=2))

For matplotlib plots, you can directly use the edgecolor or ec argument.

plt.bar(x,y, edgecolor="k")
plt.hist(x, edgecolor="k")

Equally, for pandas plots,

df.plot(kind='hist',edgecolor="k")

A complete seaborn example:

import  numpy as np
import matplotlib.pyplot as plt
import seaborn as sns

x = np.random.randn(100)
ax = sns.distplot(x, hist_kws=dict(edgecolor="k", linewidth=2))
plt.show()

enter image description here

Solution 2

As of Mar, 2021 :

sns.histplot(data, edgecolor='k', linewidth=2)

work. Using hist_kws=dict(edgecolor="k", linewidth=2) gave an error:
AttributeError: 'PolyCollection' object has no property 'hist_kws'

Share:
35,912
Colin Lindley
Author by

Colin Lindley

Updated on July 18, 2021

Comments

  • Colin Lindley
    Colin Lindley almost 3 years

    While doing some practice problems using seaborn and a Jupyter notebook, I realized that the distplot() graphs did not have the darker outlines on the individual bins that all of the sample graphs in the documentation have. I tried creating the graphs using Pycharm and noticed the same thing. Thinking it was a seaborn problem, I tried some hist() charts using matplotlib, only to get the same results.

    import matplotlib.pyplot as plt
    import seaborn as sns
    titanic = sns.load_dataset('titanic')
    plt.hist(titanic['fare'], bins=30)
    

    yielded the following graph:

    enter image description here

    Finally I stumbled across the 'edgecolor' parameter on the plt.hist() function, and setting it to black did the trick. Unfortunately I haven't found a similar parameter to use on the seaborn distplot() function, so I am still unable to get a chart that looks like it should.

    I looked into changing the rcParams in matplotlib, but I have no experience with that and the following script I ran seemed to do nothing:

    import matplotlib as mpl
    
    mpl.rcParams['lines.linewidth'] = 1
    mpl.rcParams['lines.color'] = 'black'
    mpl.rcParams['patch.linewidth'] = 1
    mpl.rcParams['patch.edgecolor'] = 'black'
    mpl.rcParams['axes.linewidth'] = 1
    mpl.rcParams['axes.edgecolor'] = 'black'
    

    I was just kind of guessing at the value I was supposed to change, but running my graphs again showed no changes.

    I then attempted to go back to the default settings using mpl.rcdefaults() but once again, no change.

    I reinstalled matplotlib using conda but still the graphs look the same. I am running out of ideas on how to change the default edge color for these charts. I am running the latest versions of Python, matplotlib, and seaborn using the Conda build.

  • mechanical_meat
    mechanical_meat about 7 years
    I'm definitely re-using: "In general seaborn is very greedy when it comes to style settings."
  • Colin Lindley
    Colin Lindley about 7 years
    Thanks for the reply, I hadn't used the hist_kws argument before. You said that there is probably no global setting for the edge color/line width in seaborn, but is there one for matplotlib's hist() function? I'm assuming that seaborn takes a lot of the default settings of hist() to create its distplot(), so changing the settings of matplotlib would change my seaborn charts as well. I am just confused on how the bins in my chart do not natively have any outlines to them, when every other chart I have seen online has them without having to explicitly give an argument.
  • ImportanceOfBeingErnest
    ImportanceOfBeingErnest about 7 years
    In matplotlib version 2 hist has no edges while in version below 2 is has them turned on by default (that may be the reason for seeing lots of examples with edges). Seaborn also has them turned off by default. But, I was actually wrong, there is a global setting called "patch.force_edgecolor" which will set edges for all patches, also the bars in barplots. I updated the answer.
  • PatrickT
    PatrickT over 2 years
    The name notwithstanding, hist_kws is an argument of seaborn.distplot(), but not of seaborn.histplot()...
  • PatrickT
    PatrickT over 2 years
    As you have discovered, hist_kws is an argument of sns.distplot(), but not of sns.histplot()...