mss
mss

Reputation: 368

How to prevent gridlines showing through when using alpha

Gridlines can be set behind the plot of a filled area by using either ax.set_axisbelow(True) or plt.rc('axes', axisbelow=True) (other stack question). But when using an alpha<1 then the gridlines will also come to the front. Is there a way to still hide the gridlines or to apply selective alpha blending? I am thinking of an object-based approach where one specifies alpha between object a and b.

The answer should also be applicable to fill_between.

Example for reproducing the problem:

import numpy as np
import matplotlib.pyplot as plt

np.random.seed(2022)
x1 = np.random.normal(0, 0.8, 1000)
x2 = np.random.normal(-2, 1, 1000)
x3 = np.random.normal(3, 2, 1000)

kwargs = dict(histtype='stepfilled', alpha=.3, density=True, bins=40)
fig, ax = plt.subplots(figsize=(9, 6))

ax.hist(x1, **kwargs)
ax.hist(x2, **kwargs)
ax.hist(x3, **kwargs)

ax.set_axisbelow(True)

ax.yaxis.grid(color='gray', linestyle='dashed')
ax.xaxis.grid(color='gray', linestyle='dashed')

enter image description here

Upvotes: 1

Views: 597

Answers (2)

Jody Klymak
Jody Klymak

Reputation: 5912

There is no capacity for conditional alphas in Matplotlib; that would be quite an API!

I would just make a white version of the histograms behind the ones I wanted to be alpha:

import numpy as np
import matplotlib.pyplot as plt

np.random.seed(2022)
x1 = np.random.normal(0, 0.8, 1000)
x2 = np.random.normal(-2, 1, 1000)
x3 = np.random.normal(3, 2, 1000)


kwargs0 = dict(histtype='stepfilled', color='w', density=True, bins=40)
kwargs = dict(histtype='stepfilled', alpha=.3, density=True, bins=40)

fig,ax = plt.subplots()
ax.hist(x1, **kwargs0)
ax.hist(x2, **kwargs0)
ax.hist(x3, **kwargs0)
ax.hist(x1, **kwargs)
ax.hist(x2, **kwargs)
ax.hist(x3, **kwargs)

ax.set_axisbelow(True)

ax.yaxis.grid(color='gray', linestyle='dashed')
ax.xaxis.grid(color='gray', linestyle='dashed')

overlapping histograms with no gridlines through them

Upvotes: 6

Trenton McKinney
Trenton McKinney

Reputation: 62513

  • This question is relevant to those using seaborn, since it's is a high-level api for matplotlib.
  • A seaborn solution similarly requires a white background, like that produced by Jody Klymak, however, there are a couple of extra parameters to tweak.
  1. If using hue=, then set color with palette=['white']*len(df.source.unique()), or palette=['white']*3.
    • The list passed to pallete= must have the same number of values as the number of unique values in the column passed to hue=.
    • If hue= is not used, set color='white'
  2. Set alpha=1 for the 'white' plot. If this is not done, the grid will be visible through the color patch and edge lines.
  • Tested in python 3.10, pandas 1.4.2, matplotlib 3.5.1, seaborn 0.11.2

Import and Sample Data

import pandas as pd
import numpy as np  # for sample data
import matplotlib.pyplot as plt
import seaborn as sns

# using the x1, x2, and x3 from the OP

# create dataframe with identifier column
data = [x1, x2, x3]
df = pd.concat([pd.DataFrame(x, columns=['values']) for x in data]).reset_index(drop=True)
df['source'] = np.repeat(['x1', 'x2', 'x3'], [len(x) for x in data])

     values source
0 -0.000422     x1
1 -0.219921     x1
2 -0.111428     x1
3  1.587749     x1
4  0.225687     x1

Plotting

With hue=

# plot
fig, ax = plt.subplots(figsize=(9, 6))

sns.histplot(data=df, x='values', stat='density', palette=['white']*3, hue='source', 
             common_norm=False, bins=40, element='step', ax=ax, alpha=1)
sns.histplot(data=df, x='values', hue='source', stat='density', common_norm=False,
             bins=40, alpha=0.3, element='step', ax=ax)
ax.set_axisbelow(True)
ax.grid()

enter image description here

Without hue=

fig, ax = plt.subplots(figsize=(9, 6))

sns.histplot(data=df, x='values', stat='density', bins=40, color='white', element='step', ax=ax, alpha=1)
sns.histplot(data=df, x='values', stat='density', bins=40, alpha=0.3, element='step', ax=ax)
ax.set_axisbelow(True)
ax.grid()

enter image description here


  • This is the plot without alpha=1 for the 'white' plot.

enter image description here

Upvotes: 0

Related Questions