title: Matplotlib: combine gradient colormap with listed colormap
body: <p>I have a DataFrame with values from (0, 1) (note that both numbers are NOT included) from some calculation.</p>
  
  <p>Then, there are some missing values that I fill with 0. </p>
  
  <p>I want to create the following colormap for the heatmap:</p>
  
  <ol>
  <li>If data is missing (==0): white colors in the heatmap (only ONE white color).</li>
  <li>If data is below threshold (eg. 0 &lt; data &lt; 0.5): light color (only ONE light color).</li>
  <li>If data is above threshold: gradient colormap of red (or any other, does not matter) colors.</li>
  </ol>
  
  <p>They key here is that I want to have exact gray and exact white colors for 1. and 2. I do not want any gradient between values below the treshold and values above the threshold.</p>
  
  <p>I have seen this question for combining two colormaps: <a href="https://stackoverflow.com/questions/31051488/combining-two-matplotlib-colormaps">Combining two matplotlib colormaps</a>, but I don't really understand where in that code it maps negative values to the distinct colormap, or how to make the second colormap non-gradient.</p>
  
  <p>Data just for the purpose of example:</p>
  
  <pre><code>data = np.random.rand(10,10) * 2 - 1.3
  data[data &lt; 0] = 0
  </code></pre>
  
  <p>And <code>ListedColormap</code>:</p>
  
  <pre><code>cmap = colors.ListedColormap(['gray', 'white', 'red'])
  bounds = [0, 0.0001, 0.1, 1.0]
  norm = colors.BoundaryNorm(bounds, cmap.N)
  
  plt.pcolor(data, cmap=cmap)
  plt.colorbar()
  plt.show()
  </code></pre>
  
  <p>And what it gives me:</p>
  
  <p><a href="https://i.stack.imgur.com/4hGKH.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/4hGKH.png" alt="example_heatmap"></a></p>
  
  <p>Once again: I want the change red part of the heatmap to a gradient (and, ideally, colorbar should not have all the colors of the same size as now).</p>
  
  <p>Thanks.</p>
  
  <p><strong>Update:</strong></p>
  
  <p>I have finally realized that it is possible to make with one colormap defined via <code>cdict</code> as in answer to this: <a href="https://stackoverflow.com/questions/16834861/create-own-colormap-using-matplotlib-and-plot-color-scale">Create own colormap using matplotlib and plot color scale</a>.</p>
  
  <p>However, I do not get at all what I expect.</p>
  
  <p>I have this <code>cdict</code>:</p>
  
  <pre><code>cdict = {'red':   ((0.0,  1.0, 1.0),
                     (0.0001,  1.0, 1.0),
                     (lower_bound, 0.99, 0.99),
                     (threshold, 0.99, 0.99),
                     (threshold + 0.0001, 0.98, 0.98),
                     (upper_bound,  0.57, 0.57),
                     (upper_bound + 0.0001,  0.0, 0.0),
                     (1.0, 0.0, 0.0)),
  
           'green': ((0.0,  1.0, 1.0),
                     (0.0001, 1.0, 1.0),
                     (lower_bound, 0.92, 0.92),
                     (threshold, 0.92, 0.92),
                     (threshold + 0.0001, 0.63, 0.63),
                     (upper_bound,  0.0, 0.0),
                     (upper_bound + 0.0001,  0.0, 0.0),
                     (1.0, 0.0, 0.0)),
  
           'blue':  ((0.0,  1.0, 1.0),
                     (0.0001,  1.0, 1.0),
                     (lower_bound, 0.82, 0.82),
                     (threshold, 0.82, 0.82),
                     (threshold + 0.0001, 0.42, 0.42),
                     (upper_bound, 0.0, 0.0),
                     (upper_bound + 0.0001,  0.0, 0.0),
                     (1.0, 0.0, 0.0))
          }
  cmap = LinearSegmentedColormap('cdict', cdict)
  </code></pre>
  
  <p>Bounds:</p>
  
  <pre><code>lower_bound = data[data != 0].min()
  upped_bound = data.max()
  threshold = 0.2
  </code></pre>
  
  <p>Where for me <code>(lower_bound, upper_bound, threshold)</code> = <code>(0.02249988938707692, 0.6575927961263812, 0.2)</code>.</p>
  
  <p>Plot:</p>
  
  <pre><code>fig, ax = plt.subplots(figsize = (15, 6))
  im = ax.imshow(data, cmap = cmap)
  cbar = ax.figure.colorbar(im, ax = ax)
  </code></pre>
  
  <p>However, I get this:</p>
  
  <p><a href="https://i.stack.imgur.com/f4utt.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/f4utt.png" alt="second_try"></a></p>
  
  <p>How is it possible? Why do I have so many black squares if black color, from my understanding of <code>cdict</code>, is assigned only to values that are above <code>upper_bound</code>, which does not make sense since <code>upper_bound</code> is maximum of all array...</p>