Changing color scale in seaborn bar plot
Here a solution:
import seaborn as sns
import numpy as np
import pandas as pd
def colors_from_values(values: pd.Series, palette_name:str, ascending=True):
'''Returns a seaborn palette reordered by value
Parameters:
values: pd.Series
palette_name:str, Seaborn valid palette name
ascending: bool, optional color sort order
'''
# convert to indices
values = values.sort_values(ascending=ascending).reset_index()
indices = values.sort_values(by=values.columns[0]).index
# use the indices to get the colors
palette = sns.color_palette(palette_name, len(values))
return np.array(palette).take(indices, axis=0)
s = pd.Series([123456, 123457, 122345, 95432],
index=pd.Index([2018, 2019, 2020, 2021], name='Year'))
sns.barplot(x=s.index, y=s.values, palette=colors_from_values(s, "rocket_r"))
Results: Plot
Here a solution:
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
sns.set(style="whitegrid", color_codes=True)
titanic = sns.load_dataset("titanic")
data = titanic.groupby("deck").size() # data underlying bar plot in question
pal = sns.color_palette("Greens_d", len(data))
rank = data.argsort().argsort() # http://stackoverflow.com/a/6266510/1628638
sns.barplot(x=data.index, y=data, palette=np.array(pal[::-1])[rank])
plt.show()
Here the output:
Note: the code currently assigns different (adjacent) colors to bars with identical height. (Not a problem in the sample plot.) While it would be nicer to use the same color for identical-height bars, the resulting code would likely make the basic idea less clear.
This solution uses the values as indices into the color palette; so that similar values get similar colors:
import seaborn as sns
import numpy as np
def colors_from_values(values, palette_name):
# normalize the values to range [0, 1]
normalized = (values - min(values)) / (max(values) - min(values))
# convert to indices
indices = np.round(normalized * (len(values) - 1)).astype(np.int32)
# use the indices to get the colors
palette = sns.color_palette(palette_name, len(values))
return np.array(palette).take(indices, axis=0)
x = np.arange(10)
y = np.random.random(10)
sns.barplot(x, y, palette=colors_from_values(y, "YlOrRd"))
Resulting in:
The double usage of the argsort
from Ulrich's answer didn't work for me. But this did:
rank = [int((max(array)-elem)*len(df)*0.75/(max(array)+1)) for elem in array]
pal = sea.color_palette("Reds_r",len(df))
Example seaborn barchart with bar heights according to y values: