[英]Discrete colorbar is missing a color
Matplotlibs离散色条在我的色彩图中缺少一种颜色定义,也用于图中。
在我的示例代码中,我有七种颜色,但颜色条只显示六种颜色,但创建色彩映射和颜色条的代码与我在互联网上找到的示例相似。 缺少标签为“180”的红色。 即使我改变了边界和刻度,也可以在颜色条中扩展米色或浅蓝色。
import matplotlib.pyplot as plt
import matplotlib
import numpy as np
import pandas as pd
# 4 marker
# 7 color
n=100
c = np.random.randint(1,8,size=n)
m = np.random.randint(1,5,size=n)
x = np.random.uniform(size=n)
y = np.random.uniform(size=n)
d_data = {'P':x, 'f':y, 'node':c, 'arch':m}
df = pd.DataFrame(d_data)
# Creating a unique list of elements
l_arch = df.arch.unique()
l_node = df.node.unique()
# Sorting is needd for good colormap
l_arch.sort()
l_node.sort()
# Creating a markers dictionary
zti_markers = ["v","^","s","o","x","+","D"]
d_marker = dict(zip(l_arch,zti_markers[:len(l_arch)] ))
# Creating a colormap and a color dictionary; A little cheat here: I know how
many different colors I need.
color_list = ['#a6cee3','#1f78b4','#b2df8a','#33a02c','#fb9a99','#e31a1c','#fdbf6f']
cmap = matplotlib.colors.ListedColormap(color_list)
norm = matplotlib.colors.BoundaryNorm(l_node, cmap.N)
d_color = dict(zip(l_node, color_list))
fig, ax = plt.subplots()
df['color'] = df['node'].apply(lambda x: d_color[x])
df['marker'] = df['arch'].apply(lambda x: d_marker[x])
for idx, row in df.iterrows():
ax.scatter(row['P'], row['f'], color=row['color'], marker=row['marker'])
cax, _ = matplotlib.colorbar.make_axes(ax)
cb = matplotlib.colorbar.ColorbarBase(cax, cmap=cmap, norm=norm,
spacing='uniform', orientation='vertical', extend='neither') #, ticks=l_node,
boundaries=l_node)
# cb = matplotlib.colorbar.ColorbarBase(cax, cmap=cmap, norm=norm,
spacing='uniform', orientation='vertical', extend='neither', ticks=l_node, boundaries=l_node)
# cb = matplotlib.colorbar.ColorbarBase(cax, cmap=cmap, norm=norm,
spacing='uniform', orientation='vertical', extend='neither', boundaries=[i-0.5 for i in l_node])
cb.set_ticklabels(['22','38','45','65','90','130','180'])
cb.set_ticks([0.5,1.5,2.5,3.5,4.5,5.5,6.5],update_ticks=True)
# cb.update_ticks()
cb.set_label('colorbar', rotation=90)
print(plt.gci()) # --> None
# gci(): Get the current colorable artist. Specifically, returns the current ScalarMappable instance (image or patch collection), or None if no images or patch collections have been defined.
plt.show()
如何修复颜色条以包含缺少的红色?
BoundaryNorm
,顾名思义,定义了颜色映射的边界。 你需要多一个边界而不是颜色。 例如,如果要将20到50之间的所有值映射到色彩映射的第一种颜色,并将所有值介于50到60之间,再映射到色彩映射的第二种颜色,则需要BoundaryNorm([20,50,60], 2)
。
在您的情况下,您实际上并不执行任何映射,因此您需要做的就是确保边界数量比颜色数量多一个。
norm = matplotlib.colors.BoundaryNorm(np.arange(len(l_node)+1), cmap.N)
如果您想在某处实际使用映射,则可以定义
norm = matplotlib.colors.BoundaryNorm(np.arange(len(l_node)+1)-0.5, cmap.N)
并使用它
ax.scatter(..., color=cmap(norm(row['node'])), )
我将在这里提供后者的完整代码,在那里我也简化了一些东西,
import matplotlib.pyplot as plt
import matplotlib
import numpy as np
import pandas as pd
# 4 marker
# 7 color
n=100
c = np.random.randint(1,8,size=n)
m = np.random.randint(1,5,size=n)
x = np.random.uniform(size=n)
y = np.random.uniform(size=n)
d_data = {'P':x, 'f':y, 'node':c, 'arch':m}
df = pd.DataFrame(d_data)
# Creating a unique list of elements
l_arch = df.arch.unique()
l_node = df.node.unique()
# Sorting is needd for good colormap
l_arch.sort()
l_node.sort()
# Creating a markers dictionary
zti_markers = ["v","^","s","o","x","+","D"]
d_marker = dict(zip(l_arch,zti_markers[:len(l_arch)] ))
# Creating a colormap and a color dictionary; A little cheat here: I know how
#many different colors I need.
color_list = ['#a6cee3','#1f78b4','#b2df8a','#33a02c','#fb9a99','#e31a1c','#fdbf6f']
cmap = matplotlib.colors.ListedColormap(color_list)
norm = matplotlib.colors.BoundaryNorm(np.arange(len(l_node)+1)-0.5, cmap.N)
d_color = dict(zip(l_node, color_list))
fig, ax = plt.subplots()
df['marker'] = df['arch'].apply(lambda x: d_marker[x])
for idx, row in df.iterrows():
ax.scatter(row['P'], row['f'], color=cmap(norm(row['node'])), marker=row['marker'])
sm = matplotlib.cm.ScalarMappable(cmap=cmap, norm=norm)
cb = fig.colorbar(sm, spacing='uniform', extend='neither')
cb.set_ticklabels(['22','38','45','65','90','130','180'])
cb.set_ticks(np.arange(len(l_node)), update_ticks=True)
cb.set_label('colorbar', rotation=90)
plt.show()
上面假设“节点”是从0开始的后续整数。如果不是这种情况,定义边界会有点复杂,例如在中间值之间取中间值,
import matplotlib.pyplot as plt
import matplotlib
import numpy as np
import pandas as pd
# 4 marker
# 7 color
n=100
c = np.random.choice([5,8,19,23,44,61,87], size=n)
m = np.random.randint(1,5,size=n)
x = np.random.uniform(size=n)
y = np.random.uniform(size=n)
d_data = {'P':x, 'f':y, 'node':c, 'arch':m}
df = pd.DataFrame(d_data)
# Creating a unique list of elements
l_arch = df.arch.unique()
l_node = df.node.unique()
# Sorting is needd for good colormap
l_arch.sort()
l_node.sort()
# Creating a markers dictionary
zti_markers = ["v","^","s","o","x","+","D"]
d_marker = dict(zip(l_arch,zti_markers[:len(l_arch)] ))
# Creating a colormap and a color dictionary; A little cheat here: I know how
#many different colors I need.
color_list = ['#a6cee3','#1f78b4','#b2df8a','#33a02c','#fb9a99','#e31a1c','#fdbf6f']
cmap = matplotlib.colors.ListedColormap(color_list)
bounds = np.concatenate(([l_node[0]-1], l_node[:-1] + np.diff(l_node)/2,[l_node[-1]+1] ))
norm = matplotlib.colors.BoundaryNorm(bounds, cmap.N)
d_color = dict(zip(l_node, color_list))
fig, ax = plt.subplots()
df['marker'] = df['arch'].apply(lambda x: d_marker[x])
for idx, row in df.iterrows():
ax.scatter(row['P'], row['f'], color=cmap(norm(row['node'])), marker=row['marker'])
sm = matplotlib.cm.ScalarMappable(cmap=cmap, norm=norm)
cb = fig.colorbar(sm, spacing='uniform', extend='neither')
cb.set_ticklabels(['22','38','45','65','90','130','180'])
cb.set_ticks(bounds[:-1]+np.diff(bounds)/2, update_ticks=True)
cb.set_label('colorbar', rotation=90)
plt.show()
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.