Matplotlib:从二进制数据填充

时间:2018-12-19 07:26:44

标签: python matplotlib

我有一个二进制numpy数组,其中包含填充数据,还有两个网格定义了数据的边界框:

data = np.random.choice([0, 1], size=12).reshape((3, 4))
xGrid = np.linspace(1, 4, 4)
yGrid = np.linspace(0.1, 0.3, 3)

我想在数据为1的任何网格点上绘制具有特定alpha值的特定颜色,而在数据为0不显示。最接近的两个matplotlib函数是

  • fill,它需要(x,y)坐标,并且不能使用此数据
  • imshowmatshow,不幸的是,它们会在任意位置绘制颜色。也就是说,它将在data == 0处绘制从颜色映射表中绘制的一些颜色。现在,我可以随意摆弄以使该颜色成为斧头的背景色,但这太讨厌了。

预计边界框的行为如下:xGrid包含三个值,并且x维度上有三个数据点。 xGrid中的每个值表示每个数据点的中心点位置,yGrid中的每个值都类似。然后,“填充数据点”对应于填充由中心坐标(x, y)定义的矩形。

实现此目标的最佳方法是什么?

4 个答案:

答案 0 :(得分:2)

了解到要使用网格交点作为中心点来绘制填充区域,我们已经

In [27]: import numpy as np 
    ...: import matplotlib.pyplot as plt 
    ...: np.random.seed(2018) 
    ...: data = np.random.choice([0, 1], size=12).reshape((3, 4)) 
    ...: xGrid = np.linspace(1, 4, 4) 
    ...: yGrid = np.linspace(0.1, 0.3, 3)                                                 

In [28]: print(data)                                                                      
[[0 0 0 1]
 [1 0 0 0]
 [1 1 1 1]]

In [29]: dx, dy = (xGrid[1]-xGrid[0])/2, (yGrid[1]-yGrid[0])/2                                    

In [30]: xli, yli = [], [] 
    ...: for y in yGrid: 
    ...:     for x in xGrid: # the x's in data are changing faster, so inner loop
    ...:         xli.append([x-dx, x+dx, x+dx, x-dx, x-dx]) 
    ...:         yli.append([y-dy, y-dy, y+dy, y+dy, y-dy]) 

In [31]: for xs, ys, Bool in zip(xli, yli, data.flatten()): 
    ...:     if Bool : plt.fill(xs, ys, color='red')
    ...: plt.gca().set_facecolor('yellow')                                      

执行上面的代码会给我enter image description here

值得一提的是,仅绘制 填充的矩形,如通过用不同的颜色填充绘图区域的背景所示。

plt.fill被记录在here中,并且在第一个for循环中创建的列表只是 x y 坐标plt.fill可能绘制的矩形的角。


效率说明

如果必须绘制几百个矩形,则上面的简单方法是可以的,如果我们进入成千上万的也许,我们想用enumerate遍历数据点,如果需要构造 x y 列表并即时绘制矩形,或者甚至为了提高性能,创建一个Rectangle补丁,将其放入一个PatchCollection,并在Matplotlib文档中的ax.add_collection-an example is available上完成循环后使用data方法,可以很容易地适应范围和{{3} }是我的新答案。

答案 1 :(得分:1)

基于此example使用imshow()来使用alpha

我正在使用@B给定的set_ticks代码。 M。

def make_rgb_transparent(rgb, bg_rgb, alpha):
    return [alpha * c1 + (1 - alpha) * c2
            for (c1, c2) in zip(rgb, bg_rgb)]

import matplotlib
from matplotlib import colors

alpha =1.0
white = np.ones((1,3))
rgb = colors.colorConverter.to_rgb('red')
rgb_new = make_rgb_transparent(rgb, (1, 1, 1), alpha)
red_white_map = colors.LinearSegmentedColormap.from_list('map_white', np.vstack((white, rgb_new)),2)

ax=plt.imshow(data,cmap=red_white_map)
ax.axes.set_xticks(np.arange(len(xGrid)))
ax.axes.set_xticklabels([str(a) for a in xGrid])
ax.axes.set_yticks(np.arange(len(yGrid)))
ax.axes.set_yticklabels([str(a) for a in yGrid])

enter image description here

答案 2 :(得分:1)

您可以使用colormap参数管理颜色。这是使用imshow的快速解决方案,可以完全控制所有参数,尤其是自定义颜色:

from pylab import imshow,show,cm
from matplotlib.colors import LinearSegmentedColormap
alpha=.7
cdict = {'blue': ((0.0, 0.0, 0.0), (1.0, 0.0, 0.0)),
 'green': ((0.0, 0.0, 0.0), (1.0, 0.0, 0.0)),
 'red': ((0.0, 0.0, 0.0), (1.0, alpha,alpha))} 
mycolors = LinearSegmentedColormap("my_colors",cdict,N=2)

ax=imshow(data,cmap=mycolors)
ax.axes.set_xticks(np.arange(len(xGrid)))
ax.axes.set_xticklabels([str(a) for a in xGrid])
ax.axes.set_yticks(np.arange(len(yGrid)))
ax.axes.set_yticklabels([str(a) for a in yGrid])
ax.axes.set_xbound(-.5,3.5)
ax.axes.set_ybound(-.5,2.5)
ax.axes.set_aspect(.2/3)

对于: enter image description here

答案 3 :(得分:1)

another answer中,我提到可以使用Rectangle补丁和PatchCollection解决可能的效率问题,这是此方法的一种实现。首先进行初始化,请注意RectanglePatchCollection

的导入
In [99]: import numpy as np 
    ...: import matplotlib.pyplot as plt 
    ...: from matplotlib.collections import PatchCollection 
    ...: from matplotlib.patches import Rectangle 
    ...:  
    ...: np.random.seed(2018) 
    ...: data = np.random.choice([0, 1], size=12).reshape((3, 4)) 
    ...: xGrid = np.linspace(1, 4, 4) 
    ...: yGrid = np.linspace(0.1, 0.3, 3) 
    ...: dx, dy = (xGrid[1]-xGrid[0])/2, (yGrid[1]-yGrid[0])/2 
    ...: print(data)                                                                             
[[0 0 0 1]
 [1 0 0 0]
 [1 1 1 1]]

接下来,我们构建PatchCollection:我们需要一个临时补丁列表,我们在data的行和 y 坐标以及每一行的列上循环和 x 坐标,如果需要,我们在补丁列表中添加一个Rectangle,最后实例化它

In [100]: patches = [] 
     ...: for y, row in zip(yGrid, data): 
     ...:     for x, col in zip(xGrid, row): 
     ...:         if col: patches.append(Rectangle((x-dx, y-dy), 2*dx, 2*dy)) 
     ...: pc = PatchCollection(patches) 

最后,在绘制过程中,我们需要两个轴的方法,因此需要plt.gca(),我们使用路径集合的方法修改矩形,将集合提交到ax,最后调用明确地要求autoscale_view方法具有正确的轴限制。

In [101]: ax = plt.gca() 
     ...: pc.set_facecolor('yellow') 
     ...: pc.set_edgecolor('black') 
     ...: ax.add_collection(pc) 
     ...: ax.autoscale_view()                                                                    

这就是结果

enter image description here