我有一个二进制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)坐标,并且不能使用此数据imshow
或matshow
,不幸的是,它们会在任意位置绘制颜色。也就是说,它将在data == 0
处绘制从颜色映射表中绘制的一些颜色。现在,我可以随意摆弄以使该颜色成为斧头的背景色,但这太讨厌了。预计边界框的行为如下:xGrid
包含三个值,并且x维度上有三个数据点。 xGrid
中的每个值表示每个数据点的中心点位置,yGrid
中的每个值都类似。然后,“填充数据点”对应于填充由中心坐标(x, y
)定义的矩形。
实现此目标的最佳方法是什么?
答案 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')
值得一提的是,仅绘制 填充的矩形,如通过用不同的颜色填充绘图区域的背景所示。
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])
答案 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)
答案 3 :(得分:1)
在another answer中,我提到可以使用Rectangle
补丁和PatchCollection
解决可能的效率问题,这是此方法的一种实现。首先进行初始化,请注意Rectangle
和PatchCollection
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()
这就是结果