Is there a 'levels'-equivalent argument for matplotlib scatter plot?

Viewed 201

I am hoping to plot observations (scatter plot) on top of model output (filled contours). To highlight regions of interest in the contour plot, I assign color scale breaks using the levels argument. When I plot the scatter on top, however, the colorscale is different. Is there a way to make the scatter color scale align with the contour color scale?

In the following example, I would like the point color to match the background color:

import numpy as np
import matplotlib.pyplot as plt

x = np.arange(0,10).tolist()
y = np.arange(0,10).tolist()
z = np.ndarray((len(x),len(y)))

for i in range(0,10):
    for j in range(0,10):
        z[i][j] = x[i]*7+y[j]*3

im = plt.contourf(z, levels=[0,10,20,30,800,900,1000], cmap='rainbow')
cbar = plt.colorbar(im)
plt.scatter(np.meshgrid(x,y)[0], np.meshgrid(x,y)[1], 
            c=z, cmap='rainbow', edgecolor='k', s=100)

Output: output

2 Answers

Matplotlib's contourf seems to have a very peculiar way to decide its color assignments (probably dating from before BoundaryNorm and related functions).

Nevertheless, the behavior can be replicated with a ListedColormap and a BoundaryNorm extracted from information of the contourf result.

Here is a slightly adapted example:

import numpy as np
import matplotlib.pyplot as plt
from matplotlib.colors import BoundaryNorm, ListedColormap

x = np.arange(0, 10)
y = np.arange(0, 10)
z = x.reshape(1, -1) * 70 + y.reshape(-1, 1) * 30
z[:, 5] = 1000

levels = [0, 10, 20, 30, 800, 900, 1000]
im = plt.contourf(x, y, z, levels=levels, cmap='rainbow')
cbar1 = plt.colorbar(im, pad=0.05)
cbar1.ax.set_title('contourf')

cmap = ListedColormap(im.get_cmap()(im.norm(im.cvalues)))
norm = BoundaryNorm(levels, len(levels) - 1)
sc = plt.scatter(np.meshgrid(x, y)[0], np.meshgrid(x, y)[1],
                 c=z.ravel(), cmap=cmap, norm=norm, edgecolor='k', s=100)
cbar2 = plt.colorbar(sc, pad=0.1)
cbar2.ax.set_title('scatter')

plt.show()

colormap from contourf for scatterplot

here my code:


#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Created on Mon Apr 19 18:16:06 2021

@author: Pietro


https://stackoverflow.com/questions/67165115/is-there-a-levels-equivalent-argument-for-matplotlib-scatter-plot

"""




import numpy as np


import matplotlib.pyplot as plt

from matplotlib.pyplot import contourf

x = np.arange(0,10).tolist()
y = np.arange(0,10).tolist()
z = np.ndarray((len(x),len(y)))

for i in range(0,10):
    for j in range(0,10):
        z[i][j] = x[i]*7+y[j]*3
        
        
fig = plt.figure()
# im = contourf(z, levels=[0,10,20,30,800,900,1000], cmap='rainbow')

im = contourf(z, levels=[0,10,20,40,60,80,100], cmap='rainbow')

# for i in im:
#     print(i) #TypeError: 'QuadContourSet' object is not iterable
    
cbar = plt.colorbar(im)

zz = []

for i in range(z.shape[0]):
    for ii in range(z.shape[1]):
        print(z[i,ii])
        zz.append(int(z[i,ii]))
print(zz)


# im = contourf(z, levels=zz, cmap='rainbow')
# cbar = plt.colorbar(im)

ax = fig.add_subplot(111)


x1,y1 = np.meshgrid(x,y)[0], np.meshgrid(x,y)[1]

# ax.scatter(x1,y1, c=z, cmap='rainbow', edgecolor='k', s=100)

ax.scatter(x1,y1, c=z, cmap='rainbow', edgecolor='k', s=100)

plt.show()

output:

enter image description here

guess I adjusted the levels to the points, aka the background is the same of the points

instead of vice-versa, but sounded more reasonable to me, let me know what you think

the code I was answering has been edited in the meanwhile, not sure if the

z values of the edited question are the same of the original post

Related