Home > Back-end >  Interactive overlay of multiple histograms in matplotlib
Interactive overlay of multiple histograms in matplotlib

Time:03-03

I have multiple plots to show that overlap each other.

import matplotlib.pyplot as plt

a = [1,2,2,3,3,3,4,4,4,4,5,5,5,5,5]
b = [5,4,4,3,3,3,2,2,2,2,1,1,1,1,1]
c = [4,5,5,6,6,7,7,7,8,8,8,9,9,10,10]

x_min, x_max = min(a   b   c), max(a   b   c)

plt.hist(a, range=(x_min,x_max), bins = 10, alpha=0.5, label="a")
plt.hist(b, range=(x_min,x_max), bins = 10, alpha=0.5, label="b")
plt.hist(c, range=(x_min,x_max), bins = 10, alpha=0.5, label="c")

plt.legend()
plt.show()

Is it possible for me to generate all the individual plots in one step, then allow the user to interactively choose which to overlay in a second step?

In this example, a correct solution would have three interactive check boxes (one fore each plot). Because there are 3 check boxes, there are 2^3=8 possible ways the user could specify the plot.

CodePudding user response:

Obviously, you have to write your own function. Matplotlib hist() returns a enter image description here

>>>The following data are valid: a c

CodePudding user response:

The problem with referring to line examples for histograms is that histograms are actually the composition of multiple lines. This means, when the button is called, you need to loop over the lines to get the expected behavior.

In the following example we see how we loop over each part p of the histogram. We change the transparency depending on its current value. Note: %matplotlib qt is required for jupyter notebook.

import matplotlib.pyplot as plt
from matplotlib.widgets import CheckButtons
%matplotlib qt 

### Specify Data And Range
a = [1,2,2,3,3,3,4,4,4,4,5,5,5,5,5]
b = [5,4,4,3,3,3,2,2,2,2,1,1,1,1,1]
c = [4,5,5,6,6,7,7,7,8,8,8,9,9,10,10]

x_min, x_max = min(a   b   c), max(a   b   c)

### Create Plots
fig, ax = plt.subplots()

p1 = ax.hist(a, range=(x_min,x_max), bins = 10, alpha=0.3, label="a")[2]
p2 = ax.hist(b, range=(x_min,x_max), bins = 10, alpha=0.3, label="b")[2]
p3 = ax.hist(c, range=(x_min,x_max), bins = 10, alpha=0.3, label="c")[2]
plt.subplots_adjust(left=0.2)

plots = [p1, p2, p3]

# Make Check Buttons
rax    = plt.axes([0.05, 0.4, 0.1, 0.15])
labels = ["a", "b", "c"]
check  = CheckButtons(rax, labels)

def action(label, default_transparency = 0.3):
    
    index = labels.index(label)
    for p in plots[index]:
        if p.get_alpha() == default_transparency:
            p.set_alpha(0.0)
        else:
            p.set_alpha(default_transparency)
        
    plt.draw()

### Run Widget
check.on_clicked(action)

plt.legend()
plt.show()
  • Related