19
ax = sns.barplot(x="size", y="algorithm", hue="ordering", data=df2, palette=sns.color_palette("cubehelix", 4))

After (or before) creating a seaborn barplot, is there a way for me to pass in hatch (fill in patterns along with the colors) values for each bar? A way to do this in seaborn or matplotlib would help a lot!

kxirog
  • 392
  • 1
  • 2
  • 9
  • 1
    I'm not sure what you mean by "each individual bar". Do you mean you want every bar to have hatches, or you want different bars to have different hatches? – mwaskom Feb 17 '16 at 23:20
  • @mwaskom Thanks for the reply! I need different bars to have different hatches. You can set all bars to have the same hatch by just passing `hatch='//'` in sns.barplot. No idea how to have different hatches in different bars though.. – kxirog Feb 17 '16 at 23:35

2 Answers2

32

You can loop over the bars created by catching the AxesSubplot returned by barplot, then looping over its patches. You can then set hatches for each individual bar using .set_hatch()

Here's a minimal example, which is a modified version of the barplot example from here.

import matplotlib.pyplot as plt
import seaborn as sns

# Set style
sns.set(style="whitegrid", color_codes=True)

# Load some sample data
titanic = sns.load_dataset("titanic")

# Make the barplot
bar = sns.barplot(x="sex", y="survived", hue="class", data=titanic);

# Define some hatches
hatches = ['-', '+', 'x', '\\', '*', 'o']

# Loop over the bars
for i,thisbar in enumerate(bar.patches):
    # Set a different hatch for each bar
    thisbar.set_hatch(hatches[i])

plt.show()

enter image description here

Thanks to @kxirog in the comments for this additional info:

for i,thisbar in enumerate(bar.patches) will iterate over each colour at a time from left to right, so it will iterate over the left blue bar, then the right blue bar, then the left green bar, etc.

tmdavison
  • 64,360
  • 12
  • 187
  • 165
  • 2
    Thanks a lot, that's exactly what I was looking for! Do you think there is a way to add the hatches to the legend as well? – kxirog Feb 18 '16 at 18:13
  • 11
    Just as so every one knows, because it took me a bit to figure it out: `for i,thisbar in enumerate(bar.patches):` iterates over each color at a time fron left to right, so it will iterate over the left blue bar, then the right blue bar, then the left green bar etc... – kxirog Feb 19 '16 at 03:12
  • 4
    @kxirog Just put `ax.legend()` after adding the hatches and before `plt.show()`. – lostsoul29 Aug 05 '16 at 20:29
  • 1
    For `box = sns.boxplot` use `box.artists` instead of `.patches`. – stefanbschneider Dec 14 '20 at 12:15
  • 2
    For `hist = sns.histplot` use `hist.collections` instead of `.patches` (at least for `element='step'`) – CodePrinz Aug 18 '21 at 08:39
  • 1
    To get the legende accordingly try to iterate over `reversed(hist.legend_.legendHandles)` (at least for my histplot). – CodePrinz Aug 25 '21 at 12:36
1

Hatches can be added to most polygons in Matplotlib, including bar, fill_between, contourf, and children of Polygon.

Hash demo

Hatch style reference

Hash styles:

hatches = ['/', '\\', '|', '-', '+', 'x', 'o', 'O', '.', '*']
hatches = ['//', '\\\\', '||', '--', '++', 'xx', 'oo', 'OO', '..', '**']
hatches = ['/o', '\\|', '|*', '-\\', '+o', 'x*', 'o-', 'O|', 'O.', '*-']

Sample code:

import matplotlib.pyplot as plt; plt.rcdefaults()
import numpy as np
import matplotlib.pyplot as plt

labels = ['G1', 'G2', 'G3', 'G4', 'G5']
men_means = [20, 34, 30, 35, 27]
women_means = [25, 32, 34, 20, 25]

x = np.arange(len(labels))  # the label locations
width = 0.25  # the width of the bars

fig, ax = plt.subplots()
rects1 = ax.bar(x - width/2, men_means, width, label='Men', hatch="//")
rects2 = ax.bar(x + width/2, women_means, width, label='Women', hatch="++")

# Add some text for labels, title and custom x-axis tick labels, etc.
ax.set_ylabel('Scores')
ax.set_xlabel('x label')
ax.set_title('Scores by group and gender')
ax.set_xticks(x, labels)
ax.legend()

ax.bar_label(rects1, padding=3)
ax.bar_label(rects2, padding=3)

fig.tight_layout()

plt.show()

enter image description here

kamyar
  • 41
  • 6