我有一个要绘制的二维numpy数组,因此我可以看到每个类别在网格上的位置。矩阵(mat)看起来像这样:
156 138 156
1300 137 156
138 138 1300
137 137 137
Run Code Online (Sandbox Code Playgroud)
我将其绘制如下:
plt.imshow(mat, cmap='tab20', interpolation='none')
Run Code Online (Sandbox Code Playgroud)
但是,我想要自定义颜色。我有一个csv,其中id与矩阵中的值相对应:
id,R,G,B
156,200,200,200
138,170,255,245
137,208,130,40
1300,63,165,76
Run Code Online (Sandbox Code Playgroud)
有没有办法让矩阵中的值与csv文件中的R,G,B值相对应?
编辑:有人要求澄清,但整个答案已删除。
每行都有一个ID和3列,分别代表R,G和B值。因此,第一行的ID 156(域特定代码)具有R 200,G 200和B 200(为灰色)。
现在,我要绘制一个二维矩阵,并且在每个坐标值为156的坐标上,我都希望该像素为灰色。与ID 1300相同,其中颜色63、165和76代表我要在矩阵中使用的绿色。
它不是特别优雅,但很简单
In [72]: import numpy as np
In [73]: import matplotlib.pyplot as plt
In [74]: a = np.mat("156 138 156;1300 137 156;138 138 1300;137 137 137")
In [75]: d = { 156: [200, 200, 200],
...: 138: [170, 255, 245],
...: 137: [208, 130, 40],
...: 1300: [63, 165, 76]}
In [76]: image = np.array([[d[val] for val in row] for row in a], dtype='B')
In [77]: plt.imshow(image);
Run Code Online (Sandbox Code Playgroud)
关键是生成一个dtype包含正确(和解包)RGB 元组的正确数组('B' 编码短无符号整数)。
在本附录中的原始问题之后交换意见之后,我将提出一个可能的解决方案来解决使用绘制相同类型数据plt.scatter()的问题(问题比我预期的要困难一些......)
import numpy as np
import matplotlib.pyplot as plt
from random import choices, randrange
######## THIS IS FOR IMSHOW ######################################
# the like of my previous answer
values = [20,150,900,1200]
rgb = lambda x=255:(randrange(x), randrange(x), randrange(x))
colord = {v:rgb() for v in values}
nr, nc = 3, 5
data = np.array(choices(values, k=nr*nc)).reshape((nr,nc))
c = np.array([[colord[v] for v in row] for row in data], dtype='B')
######## THIS IS FOR SCATTER ######################################
# This is for having the coordinates of the scattered points, note that rows' indices
# map to y coordinates and columns' map to x coordinates
y, x = np.array([(i,j) for i in range(nr) for j in range(nc)]).T
# Scatter does not expect a 3D array of uints but a 2D array of RGB floats
c1 = (c/255.0).reshape(nr*nc,3)
######## THIS IS FOR PLOTTING ######################################
# two subplots, plot immediately the imshow
f, (ax1, ax2) = plt.subplots(nrows=2)
ax1.imshow(c)
# to make a side by side comparison we set the boundaries and aspect
# of the second plot to mimic imshow's
ax2.set_ylim(ax1.get_ylim())
ax2.set_xlim(ax1.get_xlim())
ax2.set_aspect(1)
# and finally plot the data --- the size of dots `s=900` was by trial and error
ax2.scatter(x, y, c=c1, s=900)
plt.show()
Run Code Online (Sandbox Code Playgroud)
原则上,具有RGB值的矩阵是某种颜色图。这是有道理的使用颜色表中matplotlib得到颜色的曲线。在这里,这使事情变得更加复杂的原因是,这些值之间的间距不大。因此,一个想法是将它们首先映射到从0开始的整数。然后创建由这些值一个颜色表,并使用其与BoundaryNorm允许具有等距离彩条。最后,可以将颜色条的刻度标签设置回初始值。
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.colors
a =np.array([[156, 138, 156],
[1300, 137, 156],
[138, 138, 1300],
[137, 137, 137]])
ca = np.array([[156,200,200,200],
[138,170,255,245],
[137,208,130,40],
[1300,63,165,76]])
u, ind = np.unique(a, return_inverse=True)
b = ind.reshape((a.shape))
colors = ca[ca[:,0].argsort()][:,1:]/255.
cmap = matplotlib.colors.ListedColormap(colors)
norm = matplotlib.colors.BoundaryNorm(np.arange(len(ca)+1)-0.5, len(ca))
plt.imshow(b, cmap=cmap, norm=norm)
cb = plt.colorbar(ticks=np.arange(len(ca)))
cb.ax.set_yticklabels(np.unique(ca[:,0]))
plt.show()
Run Code Online (Sandbox Code Playgroud)
您可以根据数据创建一个RGB数组,直接绘制为imshow。为此,您可以使用颜色数组中的颜色对原始数组进行索引,然后对所得数组进行整形,以使其具有正确的形状以使用imshow进行绘制。
import numpy as np
import matplotlib.pyplot as plt
a =np.array([[156, 138, 156],
[1300, 137, 156],
[138, 138, 1300],
[137, 137, 137]])
ca = np.array([[156,200,200,200],
[138,170,255,245],
[137,208,130,40],
[1300,63,165,76]])
u, ind = np.unique(a, return_inverse=True)
c = ca[ca[:,0].argsort()][:,1:]/255.
b = np.moveaxis(c[ind][:,:,np.newaxis],1,2).reshape((a.shape[0],a.shape[1],3))
plt.imshow(b)
plt.show()
Run Code Online (Sandbox Code Playgroud)
结果与上面相同,但没有颜色条(因为此处没有要映射的数量)。
| 归档时间: |
|
| 查看次数: |
5714 次 |
| 最近记录: |