Here is my picture. I need to make label for those bars however every upper layer contains lower layer – so the label should containt grouped colors, i.e. blue – dataset 1, blue/orange – dataset 2, blue/orange/green – dataset 3 and finally blue/orange/green/purple – dataset 4. Is it plausible to make it? Thank you.
binwidth = 1 n, bins, patches = ax1.hist(C, bins=range(81, 105, binwidth), density=False, histtype='barstacked' , edgecolor='gray', color=barvy_histogram,linewidth=0.3) hatches = ['//','x','..','oo'] for patch_set, hatch in zip(patches, hatches): for patch in patch_set.patches: patch.set_hatch(hatch) patch.set_linewidth=0.1 patch.set_color='gray' mpl.rcParams['hatch.linewidth'] = 0.5
Advertisement
Answer
The following approach uses the tuple legend handler (HandlerTuple
) to combine the legend handles. It produces a horizontal layout, while maybe a vertical stacking would be more interesting.
The code starts with creating some test data, supposing C
is an Nx4
array of integers. The bin edges are set at halves to make sure that floating point accuracy wouldn’t place values in the wrong bin.
import matplotlib as mpl import matplotlib.pyplot as plt from matplotlib.legend_handler import HandlerTuple import numpy as np # first, create some test data C = (np.random.normal(0.001, 1, (100, 20)).cumsum(axis=0) * 1.2 + 90).astype(int).reshape(-1, 4) c_min = C.min() c_max = C.max() mpl.rcParams['hatch.linewidth'] = 0.5 fig, ax1 = plt.subplots(figsize=(12, 5)) binwidth = 1 colors = plt.cm.Set2.colors[:C.shape[1]] _, _, patches = ax1.hist(C, bins=np.arange(c_min - 0.5, c_max + binwidth, binwidth), density=False, histtype='barstacked', edgecolor='gray', color=colors, linewidth=0.3, label=[f'N={p}' for p in range(25, 101, 25)]) hatches = ['//', 'x', '..', 'oo'] for patch_set, hatch in zip(patches, hatches): for patch in patch_set.patches: patch.set_hatch(hatch) patch.set_linewidth = 0.1 handles, labels = ax1.get_legend_handles_labels() ax1.legend(handles=[tuple(handles[:i + 1]) for i in range(C.shape[1])], labels=labels, handlelength=6, handler_map={tuple: HandlerTuple(ndivide=None, pad=0)}) plt.show()