I have a very wide range of data that I plot using seaborn bar plot. As I use hue, the two different colors are the same for all the data, but I want that every single bar is a different color.
#This is the colors I want for every bar: palette = ["#fee090","#fdae61","#4575b4","#313695","#e0f3f8","#abd9e9","#d73027", "#a50026"]
ax3=sns.barplot(data=Results,x="Mineral ", y="FLT",hue="Media size ",palette=palette,ci=None, ecolor='black',edgecolor='black',)
#this is my data frame
| Media size | Material bead | Mineral | FLT |
|---|---|---|---|
| 1.70 | MinFree | 0.00 | 14.86 |
| 1.70 | MinFree | 0.00 | 14.34 |
| 3.00 | MinFree | 0.00 | 9.95 |
| 3.00 | MinFree | 0.00 | 9.68 |
| 1.70 | GIC | 4.00 | 14.87 |
| 1.70 | GIC | 4.00 | 14.38 |
| 3.00 | GIC | 4.00 | 11.80 |
| 3.00 | GIC | 4.00 | 11.12 |
| 1.70 | IC60 | 4.00 | 11.80 |
| 1.70 | IC60 | 4.00 | 11.12 |
| 3.00 | IC60 | 4.00 | 9.24 |
| 3.00 | IC60 | 4.00 | 8.99 |
| 1.70 | BHX | 4.00 | 9.85 |
| 1.70 | BHX | 4.00 | 9.70 |
| 3.00 | BHX | 4.00 | 7.17 |
| 3.00 | BHX | 4.00 | 6.70 |
#This is the result: result and as you can see it just takes the two first values of the pallette.
Another doubt. When I run the ci=69 for standard error, the error bars that I obtain are not correct. In some bars are mising, it makes somehting weird. Any hint on this?
THANKS
When working with hue, seaborn assigns one color per hue value. In this case there seem to be two hue values (1.70 and 3.00), so two colors are used.
To give each bar a separate color, you could iterate through the generated bars and manually assign the colors. Note that for each hue value, a container is created for the bars with that hue.
You can use the HandlerTuple legend handler to show all color in the legend.
import matplotlib.pyplot as plt
from matplotlib.legend_handler import HandlerTuple
import seaborn as sns
import pandas as pd
palette = ["#fee090", "#fdae61", "#4575b4", "#313695", "#e0f3f8", "#abd9e9", "#d73027", "#a50026"]
df = pd.read_html('https://stackoverflow.com/questions/74617540')[0]
ax = sns.barplot(data=df, x='Material bead', y='FLT', hue='Media size', palette=palette, errorbar=None,
edgecolor='black') ###errorbar=('ci', 69))
for bars, colors in zip(ax.containers, (palette[0::2], palette[1::2])):
for bar, color in zip(bars, colors):
bar.set_facecolor(color)
ax.legend(handles=[tuple(bar_group) for bar_group in ax.containers],
labels=[bar_group.get_label() for bar_group in ax.containers],
title=ax.legend_.get_title().get_text(),
handlelength=4, handler_map={tuple: HandlerTuple(ndivide=None, pad=0.1)})
sns.despine()
plt.show()

If you want to color the bars and hatch one of the hues with a pattern, you can call set_hatch() on those bars. You could update the legend already created by seaborn to indicate the hatching on a grey background. (Creating a new legend, as in the previous example, would also work here. But note that hatching is not so easy to see in small areas.)
import matplotlib.pyplot as plt
import seaborn as sns
import pandas as pd
df = pd.read_html('https://stackoverflow.com/questions/74617540')[0]
ax = sns.barplot(data=df, x='Material bead', y='FLT', hue='Media size', palette=['lightgrey', 'lightgrey'],
errorbar=None, edgecolor='black')
palette = ["#fee090", "#4575b4", "#e0f3f8", "#d73027"]
for bars, hatch, legend_handle in zip(ax.containers, ['', '//'], ax.legend_.legendHandles):
for bar, color in zip(bars, palette):
bar.set_facecolor(color)
bar.set_hatch(hatch)
# update the existing legend, use twice the hatching pattern to make it denser
legend_handle.set_hatch(hatch + hatch)
sns.despine()
plt.show()

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