Python 二维对象数组的可视化表示

Python 二维对象数组的可视化表示,python,numpy,matplotlib,Python,Numpy,Matplotlib,假设我获得一个对象数组,例如 array([[ 0 , 0 , 'g', 'g', 'g'], [ 0 , 0 , 0 , 'g', 'g'], ['d', 0 , 1 , 1 , 'g'], ['d', 'd', 1 , 1 , 'g'], ['d', 'd', 'd', 'd', 'g']], dtype=object) 我希望能够像在numpy阵列上使用plt.imshow一样直观地看到这一点。更具体地说,我希望看到

假设我获得一个对象数组,例如

array([[ 0 ,  0 , 'g', 'g', 'g'],
       [ 0 ,  0 ,  0 , 'g', 'g'],
       ['d',  0 ,  1 ,  1 , 'g'],
       ['d', 'd',  1 ,  1 , 'g'],
       ['d', 'd', 'd', 'd', 'g']], dtype=object)
我希望能够像在numpy阵列上使用plt.imshow一样直观地看到这一点。更具体地说,我希望看到一个图像,其中g区域是某种颜色,可能是黄色,d区域是某种颜色,可能是绿色,可能是一个颜色映射,它会随着数值0、1、2的变化而变化。。。如下图所示


编辑:数值可能是非整数,只是浮动。

首先,让我们看看文档中的imshow:

从文档中:

显示图像,即二维常规光栅上的数据

而图像输入X状态的文档:

X:类似阵列或PIL图像

图像数据。支持的阵列形状包括:

M、 N:带有标量数据的图像。数据是使用彩色地图可视化的

M、 N,3:RGB值为0-1浮点或0-255整数的图像

M、 N,4:RGBA值为0-1浮点或0-255整数的图像,即包括透明度

从文档中可以看出,imshow完全符合float数据类型数组,因此我们需要找到一种方法,将您发布的数组的数据类型从object转换为float

所以,正如我在评论中所概述的:我在想这样的事情

import numpy as np
import matplotlib.pyplot as plt

foo = np.array([[ 0 ,  0 , 'g', 'g', 'g'], 
                [ 0 ,  0 ,  0 , 'g', 'g'],
                ['d',  0 ,  1 ,  1 , 'g'],
                ['d', 'd',  1 ,  1 , 'g'],
                ['d', 'd', 'd', 'd', 'g']], dtype=object)

# replace chars by reserved numbers
np.place(foo, foo=='g', -1)
np.place(foo, foo=='d', -2)

# change dtype from object to float
foo = foo.astype(np.float32)

# sanity check
print(foo)

# plot
plt.imshow(foo)
我没有调整cmap,因为它上面真的是糖- 结果如下:

问题:

imshow声明期望输入数组为dtype.float,因此采用转换方法。 奖金:

每个字符的保留数字可以根据您的要求映射到cmap中的专用颜色。 不利因素:

不能很好地扩展任意字符。 确实使用保留数字作为替换,因此需要知道并固定其余数字的数值集。
我仍然希望这个答案能帮助你。干杯

首先,让我们看看文档中的imshow:

从文档中:

显示图像,即二维常规光栅上的数据

而图像输入X状态的文档:

X:类似阵列或PIL图像

图像数据。支持的阵列形状包括:

M、 N:带有标量数据的图像。数据是使用彩色地图可视化的

M、 N,3:RGB值为0-1浮点或0-255整数的图像

M、 N,4:RGBA值为0-1浮点或0-255整数的图像,即包括透明度

从文档中可以看出,imshow完全符合float数据类型数组,因此我们需要找到一种方法,将您发布的数组的数据类型从object转换为float

所以,正如我在评论中所概述的:我在想这样的事情

import numpy as np
import matplotlib.pyplot as plt

foo = np.array([[ 0 ,  0 , 'g', 'g', 'g'], 
                [ 0 ,  0 ,  0 , 'g', 'g'],
                ['d',  0 ,  1 ,  1 , 'g'],
                ['d', 'd',  1 ,  1 , 'g'],
                ['d', 'd', 'd', 'd', 'g']], dtype=object)

# replace chars by reserved numbers
np.place(foo, foo=='g', -1)
np.place(foo, foo=='d', -2)

# change dtype from object to float
foo = foo.astype(np.float32)

# sanity check
print(foo)

# plot
plt.imshow(foo)
我没有调整cmap,因为它上面真的是糖- 结果如下:

问题:

imshow声明期望输入数组为dtype.float,因此采用转换方法。 奖金:

每个字符的保留数字可以根据您的要求映射到cmap中的专用颜色。 不利因素:

不能很好地扩展任意字符。 确实使用保留数字作为替换,因此需要知道并固定其余数字的数值集。
我仍然希望这个答案能帮助你。干杯

我认为在这种类型的应用程序中,一个好的、信息丰富的色条是绝对必要的,即使OP在他们的Q中没有提到色条

下面的代码基于数组中使用的整数仅为0和1的假设

import numpy as np
import matplotlib.pyplot as plt
from itertools import count

a = np.array([[ 0 ,  0 , 'g', 'g', 'g'], 
              [ 0 ,  0 ,  0 , 'g', 'g'], 
              ['d',  0 ,  1 ,  1 , 'g'], 
              ['d', 'd',  1 ,  1 , 'g'], 
              ['d', 'd', 'd', 'd', 'g']], dtype=object)

# we want to build a dictionary mapping objects to integers
seq2 = count(2) # we don't know in advance how many different objects we'll see
d = {0:0, 1:1}  # but we know that the integers are either 0 or 1
for o in a.flatten():  
    if o not in d: d[o] = next(seq2)

# with the help of the dictionary, here it is a plottable matrix
b = np.array([d[x] for x in a.flatten()]).reshape(a.shape)

N = len(d)
# to avoid a continuous colorbar, we sample the needed colors
cmap = plt.cm.get_cmap('viridis', N) 

# eventually,
# we can plot the matrix, the colorbar and fix the colorbar labelling
plt.imshow(b, cmap=cmap)
cb = plt.colorbar(drawedges=True)
dc = (N-1)/N
cb.set_ticks([dc*(n+1/2) for n in range(N)])
cb.set_ticklabels([v for k, v in sorted((v,k) for k,v in d.items())])

plt.show()
后脚本

另一个答案提到重点是我的

从文档中可以看出,imshow完全符合float数据类型数组

但是① 唯一的要求是关于标量数据,因为到colormap的连续映射被委托给matplotlib.colors.Normalize类② 使用专门的matplotlib.colors.Normalize子类,可以直接使用矩阵中的单个整数来索引与每个颜色映射关联的颜色列表,例如

In [34]: import matplotlib.pyplot as plt 
    ...: import numpy as np 
    ...: from matplotlib.colors import NoNorm 
    ...: %matplotlib 
    ...:  
    ...: mat_r, mat_i = (np.array(np.arange(6), dtype=float)[None,:], 
    ...:                 np.array(np.arange(6), dtype=int)[None,:]) 
    ...:  
    ...: def show(ax, mat, title, norm=None): 
    ...:     ax.imshow(mat, norm=norm) 
    ...:     ax.set_title(title) 
    ...:     ax.set_yticks([]) 
    ...:  
    ...: fig, axes = plt.subplots(6,1, figsize=(3, 6)) 
    ...:  
    ...: for ax, mat, norm, title in zip( 
    ...:   axes, 
    ...:   (mat_r, mat_i, mat_i, 30*mat_r, 30*mat_i, 30*mat_i), 
    ...:   (None, None, NoNorm(), None, None, NoNorm()), 
    ...:   ('mat_r','mat_i','mat_i NoNorm','30×mat_r','30×mat_i','30×mat_i NoNorm')): 
    ...:      show(ax, mat, title, norm) 
    ...: fig.tight_layout()                                                               


我认为在这种类型的应用程序中,一个好的、信息丰富的色条是绝对必要的,即使OP在他们的Q中没有提到色条

下面的代码基于数组中使用的整数仅为0和1的假设

import numpy as np
import matplotlib.pyplot as plt
from itertools import count

a = np.array([[ 0 ,  0 , 'g', 'g', 'g'], 
              [ 0 ,  0 ,  0 , 'g', 'g'], 
              ['d',  0 ,  1 ,  1 , 'g'], 
              ['d', 'd',  1 ,  1 , 'g'], 
              ['d', 'd', 'd', 'd', 'g']], dtype=object)

# we want to build a dictionary mapping objects to integers
seq2 = count(2) # we don't know in advance how many different objects we'll see
d = {0:0, 1:1}  # but we know that the integers are either 0 or 1
for o in a.flatten():  
    if o not in d: d[o] = next(seq2)

# with the help of the dictionary, here it is a plottable matrix
b = np.array([d[x] for x in a.flatten()]).reshape(a.shape)

N = len(d)
# to avoid a continuous colorbar, we sample the needed colors
cmap = plt.cm.get_cmap('viridis', N) 

# eventually,
# we can plot the matrix, the colorbar and fix the colorbar labelling
plt.imshow(b, cmap=cmap)
cb = plt.colorbar(drawedges=True)
dc = (N-1)/N
cb.set_ticks([dc*(n+1/2) for n in range(N)])
cb.set_ticklabels([v for k, v in sorted((v,k) for k,v in d.items())])

plt.show()
后脚本

另一个答案提到重点是我的

从文档中可以看出,imshow完全符合float数据类型数组

但是① 唯一的要求是关于标量数据,因为到colormap的连续映射被委托给matplotlib.colors.Normalize类② 使用专门的matplotlib.colors.Normalize子类,可以直接使用矩阵中的单个整数来索引与每个颜色映射关联的颜色列表,例如

In [34]: import matplotlib.pyplot as plt 
    ...: import numpy as np 
    ...: from matplotlib.colors import NoNorm 
    ...: %matplotlib 
    ...:  
    ...: mat_r, mat_i = (np.array(np.arange(6), dtype=float)[None,:], 
    ...:                 np.array(np.arange(6), dtype=int)[None,:]) 
    ...:  
    ...: def show(ax, mat, title, norm=None): 
    ...:     ax.imshow(mat, norm=norm) 
    ...:     ax.set_title(title) 
    ...:     ax.set_yticks([]) 
    ...:  
    ...: fig, axes = plt.subplots(6,1, figsize=(3, 6)) 
    ...:  
    ...: for ax, mat, norm, title in zip( 
    ...:   axes, 
    ...:   (mat_r, mat_i, mat_i, 30*mat_r, 30*mat_i, 30*mat_i), 
    ...:   (None, None, NoNorm(), None, None, NoNorm()), 
    ...:   ('mat_r','mat_i','mat_i NoNorm','30×mat_r','30×mat_i','30×mat_i NoNorm')): 
    ...:      show(ax, mat, title, norm) 
    ...: fig.tight_layout()                                                               


欢迎来到SO!您是否尝试过编写代码来完成此任务?如果是这样的话,你能把它作为一个例子来分享并描述出哪里出了问题吗?如果没有,请尝试为其编码
self,然后当你陷入困境时,问一个关于特定编码问题的具体问题。我认为可能是愚蠢的,但最直接的方法是将你的np.array转换为dtype float32,然后使用适当的cmap进行imshow,不是吗?@ggorlen我想这个问题的真正目标是如何将imshow与对象数据类型的numpy数组一起使用?我想知道。。。您的对象是整数(可能表示布尔值、0/1)和字符:您真正的问题数组是否相同,即0/1加字符?欢迎使用!您是否尝试过编写代码来完成此任务?如果是这样的话,你能把它作为一个例子来分享并描述出哪里出了问题吗?如果没有,请尝试自己编写代码,然后在遇到问题时问一个关于特定编码问题的具体问题。我认为最简单、最直接的方法可能是将np.array转换为dtype float32,然后使用适当的cmap显示,不是吗?@ggorlen我想这个问题的真正目标是如何将imshow与对象数据类型的numpy数组一起使用?我想知道。。。您的对象是整数(可能表示布尔值、0/1)和字符:您真正的问题数组是否相同,即0/1加字符?