Hagbard
Hagbard

Reputation: 3680

Setting different transparency values for different categories in a seaborn scatterplot

This question is related to a previous question I posted here. My code for my seaborn scatterplot looks as follows:

import matplotlib.pyplot as plt
import pandas as pd
import seaborn as sns

df = pd.DataFrame()
df['First PCA dimension'] = [1,2,3,4]
df['Second PCA dimension'] = [0,5,5,7]
df['Third PCA dimension'] = [1,2,6,4]
df['Data points'] = [1,2,3,4]

plt.figure(figsize=(42,30))
plt.title('2-D PCA of my data points',fontsize=32)

colors = ["#FF9926", "#2ACD37","#FF9926", "#FF0800"]
b = sns.scatterplot(x="First PCA dimension", y="Second PCA dimension", hue="Data points", palette=sns.color_palette(colors), data=df, legend="full", alpha=0.3)
sns.set_context("paper", rc={"font.size":48,"axes.titlesize":48,"axes.labelsize":48})

b.set_ylabel('mylabely', size=54)
b.set_xlabel('mylabelx', size=54)
b.set_xticklabels([1,2,3,4,5,6,7,8], fontsize = 36)

lgnd = plt.legend(fontsize='22')
for handle in lgnd.legendHandles:
    handle.set_sizes([26.0])

plt.show()

The alpha value of 0.3 sets a transparency value for each point in my scatterplot. However, I would like to have a different transparency value for each data point (based on the category it belongs to) instead. Is this possible by providing a list of alpha values, similar to the way I provide a list of colours in the example above?

Upvotes: 1

Views: 1378

Answers (1)

Cai
Cai

Reputation: 2120

As noted in comments, this is something you can't currently do with seaborn.

However, you can hack it by using key colours for the markers, and find-replacing those colours using PathCollection.get_facecolor() and PathCollection.set_facecolor() with RGBA colours.

So for example, I needed a swarmplot on top of a violinplot, with certain classes of points at different opacities. To change greys into transparent blacks (what I needed to do), we can do:

seaborn.violinplot(...)
points = seaborn.swarmplot(...)

for c in points.collections:
    if not isinstance(c, PathCollection):
        continue
    fc = c.get_facecolor()
    if fc.shape[1] == 4:
        for i, r in enumerate(fc):
            # change mid-grey to 50% black
            if numpy.array_equiv(r, array([0.5, 0.5, 0.5, 1])):
                fc[i] = array([0, 0, 0, 0.5])
            # change white to transparent
            elif numpy.array_equiv(r, array([1, 1, 1, 1])):
                fc[i] = array([0, 0, 0, 0])
        c.set_facecolor(fc)

Very awful, but it got me what I needed for a one-shot graphic.

Upvotes: 1

Related Questions