I have a bar plot created using seaborn. For example, the plot can be created as follows:
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
data1 = pd.DataFrame(np.random.rand(17,3), columns=['A','B','C']).assign(Location=1)
data2 = pd.DataFrame(np.random.rand(17,3)+0.2, columns=['A','B','C']).assign(Location=2)
data3 = pd.DataFrame(np.random.rand(17,3)+0.4, columns=['A','B','C']).assign(Location=3)
cdf = pd.concat([data1, data2, data3])
mdf = pd.melt(cdf, id_vars=['Location'], var_name=['Letter'])
ax = sns.barplot(x="Location", y="value", hue="Letter", data=mdf, errwidth=0)
ax.legend(loc='upper center', bbox_to_anchor=(0.5, 1.2), ncol=3, fancybox=True, shadow=True)
plt.show()
This gives the following plot I would like to do customize the chart as follows:
Removing the face color is easy, just do ax.set_facecolor('w')
, although this will make the grid lines invisible. I'd recommend using sns.set_style('whitegrid')
before plotting instead, you'll get a white background with only horizontal grid lines in grey.
As for the different has patterns, this is a little trickier with seaborn, but it can be done. You can pass the hatch
keyword argument to barplot, but it'll be applied to each bar, which doesn't really help you distinguish them. Unfortunately, passing a dictionary here doesn't work. Instead, you can iterate over the bars after they're constructed to apply a hatch. You'll have to calculate the number of locations, but this is pretty straightforward with pandas. It turns out that seaborn actually plots each hue before moving on to the next hue, so in your example it would plot all blue bars, then all green bars, then all red bars, so the logic is pretty straightforward:
num_locations = len(mdf.Location.unique())
hatches = itertools.cycle(['/', '//', '+', '-', 'x', '\\', '*', 'o', 'O', '.'])
for i, bar in enumerate(ax.patches):
if i % num_locations == 0:
hatch = next(hatches)
bar.set_hatch(hatch)
So the full script is
import itertools
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
sns.set_style('whitegrid')
data1 = pd.DataFrame(np.random.rand(17, 3), columns=['A', 'B', 'C']).assign(Location=1)
data2 = pd.DataFrame(np.random.rand(17, 3) + 0.2, columns=['A', 'B', 'C']).assign(Location=2)
data3 = pd.DataFrame(np.random.rand(17, 3) + 0.4, columns=['A', 'B', 'C']).assign(Location=3)
cdf = pd.concat([data1, data2, data3])
mdf = pd.melt(cdf, id_vars=['Location'], var_name=['Letter'])
ax = sns.barplot(x="Location", y="value", hue="Letter", data=mdf, errwidth=0)
num_locations = len(mdf.Location.unique())
hatches = itertools.cycle(['/', '//', '+', '-', 'x', '\\', '*', 'o', 'O', '.'])
for i, bar in enumerate(ax.patches):
if i % num_locations == 0:
hatch = next(hatches)
bar.set_hatch(hatch)
ax.legend(loc='upper center', bbox_to_anchor=(0.5, 1.1), ncol=3, fancybox=True, shadow=True)
plt.show()
And I get the output
Reference for setting hatches and the different hatches available: http://matplotlib.org/examples/pylab_examples/hatch_demo.html
Note: I adjusted your bbox_to_anchor
for the legend because it was partially outside of the figure on my computer.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With