Home > Blockchain >  Seaborn Striplot data visualization not applying colors to markers/bars/strips
Seaborn Striplot data visualization not applying colors to markers/bars/strips

Time:12-06

When creating a stripplot with seaborn, the code creates a striplot perfectly. Applies colors to the legend and all. Except the color is not applying to the various strips in within the stripplot. Appreciate the seaborn/matplotlib experts here, because I am at a loss. Code is below. Picture attached below with my results.

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

#set seaborn plotting aesthetics
sns.set_style("whitegrid")

data = [[2016.0, 0.4862, 0.4115, 0.3905, 0.3483, 0.1196],
 [2017.0, 0.4471, 0.4096, 0.3725, 0.2866, 0.1387],
 [2018.0, 0.4748, 0.4016, 0.3381, 0.2905, 0.2012],
 [2019.0, 0.4705, 0.4247, 0.3857, 0.3333, 0.2457],
 [2020.0, 0.4755, 0.4196, 0.3971, 0.3825, 0.2965]]

# cols = ['attribute_time', '100-81%', '80-61%', '60-41%', '40-21%', '20-0%']
cols = ['attribute_time', '100-81 percentile', '80-61 percentile', '60-41 percentile', '40-21 percentile', '20-0 percentile']

df = pd.DataFrame(data, columns=cols)

# Just to get rid of the decimals.
df['attribute_time'] = df['attribute_time'].astype('int') 
print(df)
df.columns = ['attribute_time', '100-81 percentile', '80-61 percentile', '60-41 percentile', '40-21 percentile', '20-0 percentile']
df = df.melt(id_vars = ['attribute_time'],
    value_name = 'pct_value',
    var_name = 'pct_range')
print(df.head(20))

print(df['pct_range'].unique())

# # Create a dictionary mapping subgroup values to colors
palette_colors = dict(zip(list(df['pct_range'].unique()), ['blue', 'orange', 'green', 'red', 'purple']))
print(palette_colors)

fig, ax = plt.subplots()

for year, value in zip(df['attribute_time'],df['pct_value']):
    ax.text(year - 2016, value, str(value), ha = 'center', va = 'bottom', fontsize = 'small',)

sns.stripplot(
    data = df,
    x = 'attribute_time',
    y = 'pct_value',
    hue = 'pct_range',
    palette=palette_colors,
    jitter = False,
    marker = '_',
    size = 25,
    linewidth = 2,
    ax = ax
).legend(fontsize=7)

plt.show()

stripplot without colors appliers to markers

CodePudding user response:

Matplotlib has two types of markers. Most are filled (e.g. as circle with a border). Some are unfilled (e.g. a horizontal line).

Seaborn uses the hue color only for the interior, and uses a fixed color (default black) for the borders (edges). If I try to run your code, I get a warning from matplotlib complaining that a face color is given for unfilled markers. You can simply put edgecolor='face' to give the face color to the edges. (Matplotlib still gives the same warning, but does color the markers via the hue color.)

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

# set seaborn plotting aesthetics
sns.set_style("whitegrid")

data = [[2016.0, 0.4862, 0.4115, 0.3905, 0.3483, 0.1196],
        [2017.0, 0.4471, 0.4096, 0.3725, 0.2866, 0.1387],
        [2018.0, 0.4748, 0.4016, 0.3381, 0.2905, 0.2012],
        [2019.0, 0.4705, 0.4247, 0.3857, 0.3333, 0.2457],
        [2020.0, 0.4755, 0.4196, 0.3971, 0.3825, 0.2965]]
cols = ['attribute_time', '100-81 percentile', '80-61 percentile', '60-41 percentile', '40-21 percentile', '20-0 percentile']

df = pd.DataFrame(data, columns=cols)
# Just to get rid of the decimals.
df['attribute_time'] = df['attribute_time'].astype('int')
df_long = df.melt(id_vars=['attribute_time'],
             value_name='pct_value',
             var_name='pct_range')
# Create a dictionary mapping subgroup values to colors
palette_colors = dict(zip(list(df_long['pct_range'].unique()), plt.cm.get_cmap('Set1').colors))

fig, ax = plt.subplots()

for year, value in zip(df_long['attribute_time'], df_long['pct_value']):
     ax.text(year - 2016, value, str(value), ha='center', va='bottom', fontsize='small', )

sns.stripplot(data=df_long,
              x='attribute_time',
              y='pct_value',
              hue='pct_range',
              palette=palette_colors,
              jitter=False,
              marker='_',
              size=25,
              linewidth=2,
              edgecolor='face',
              ax=ax)
ax.legend(fontsize=7)

plt.show()

sns.stripplot with edgecolor='face'

  • Related