简体   繁体   中英

How to change scatter plot color according to certain rule

I have to do a scatter plot that has colors depending on a third variable. If the variable is between 0 and 1, give "blue", 1-2, red, 2-3, purple, 3-4, green, 4-5 gray. How can I do that ?

x = [1,2,3,4,5]
y = [3,4,2,3,4]
c = [1,2,4,0.5,5]

If you want specific boundaries for the colormap you can use mpl.colors.BoundaryNorm together with mpl.colors.ListedColormap .

import matplotlib.pyplot as plt
import matplotlib as mpl

x = [1,2,3,4,5]
y = [3,4,2,3,4]
c = [1,2,4,0.5,5]

cmap = mpl.colors.ListedColormap(['blue','red','magenta', 'green', 'gray'])
c_norm = mpl.colors.BoundaryNorm(boundaries=[0,1,2,3,4,5], ncolors=5)
plt.scatter(x, y, c=c, s=200, cmap=cmap, norm=c_norm)
plt.colorbar()
plt.show()

Which gives this plot:

在此处输入图片说明

You can create and use a listed colormap:

import matplotlib as mpl
import matplotlib.pyplot as plt

x = [1,2,3,4,5]
y = [3,4,2,3,4]
c = [1,2,4,0.5,5]    
cmap = mpl.colors.ListedColormap( [[1., 0., 0.],
                                   [0., 1., 0.],
                                   [0., 0., 1.]])
plt.scatter(x, y, c=c, s=100, cmap=cmap)
plt.show()

Here is another example, coloring a scatter plot depending on age.

The BoundaryNorm set the boundaries for each age range and associate a color to each.

If, for example there are age ranges < 18, 18-40, 40-65, 65-80, > 80 , you could list these boundaries as [18,40,65,80] . The BoundaryNorm needs one more bound than the number of colors, so you could add 0 at the front and 100 at the end.

You can create a colormap from an existing colormap, giving the number of colors needed: plt.cm.get_cmap('plasma_r', len(boundaries)+1) or as a ListedColormap, giving it an explicit list of colors: matplotlib.colors.ListedColormap([...]) .

Example code:

import matplotlib
from matplotlib import pyplot as plt
import pandas as pd
import numpy as np

N = 30
df = pd.DataFrame({'x': np.random.randint(4,12,N),
                   'y': np.random.randint(4,10,N),
                   'birthdt': np.random.randint(1,95, N)})
boundaries = [18, 40, 65, 80]
cmap = matplotlib.colors.ListedColormap(['limegreen', 'dodgerblue', 'crimson', 'orange', 'fuchsia'])
# cmap = plt.cm.get_cmap('plasma_r', len(boundaries) + 1)
norm = matplotlib.colors.BoundaryNorm([0]+boundaries+[100], len(boundaries)+1)

plt.scatter(df.x, df.y, s=60, c=df.birthdt, cmap=cmap, norm=norm)
cbar = plt.colorbar(extend='max')
cbar.ax.set_ylabel('Age')
plt.show()

示例图

If you'd like the colorbar separations in proportion to the age ranges, you can try:

import matplotlib
from matplotlib import pyplot as plt
import pandas as pd
import numpy as np

N = 30
df = pd.DataFrame({'x': np.random.randint(4, 12, N),
                   'y': np.random.randint(4, 10, N),
                   'birthdt': np.random.randint(1, 95, N)})
boundaries = [18, 30, 65, 80]
max_age = 100
base_colors = ['limegreen', 'dodgerblue', 'crimson', 'orange', 'fuchsia']
full_colors = [c for c, b0, b1 in zip(base_colors, [0] + boundaries, boundaries + [max_age]) for i in range(b1 - b0)]
cmap_full = matplotlib.colors.ListedColormap(full_colors)
norm_full = matplotlib.colors.Normalize(vmin=0, vmax=max_age)
plt.scatter(df.x, df.y, s=60, c=df.birthdt, cmap=cmap_full, norm=norm_full)
cbar = plt.colorbar(extend='max', ticks=boundaries)
cbar.ax.set_ylabel('Age')
plt.show()

按比例颜色条

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM