[英]Matplotlib: Fill from binary data
我有一個包含填充數據的二進制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
,並沒有當數據是0
。 兩個最接近的matplotlib函數是
fill
,它需要(x,y)坐標,並且不能使用此數據 imshow
或matshow
,不幸的是,它們會在各處繪制一些顏色。 也就是說,無論data == 0
,它還將繪制從顏色映射表中繪制的某些顏色。 現在,我可以隨意擺弄以使該顏色成為斧頭的背景色,但這太討厭了。 預期邊界框的行為如下: xGrid
包含三個值,並且x維度上有三個數據點。 xGrid
每個值表示每個數據點的中心點的位置,而yGrid
類似。 然后,“填充數據點”對應於填充由中心坐標( x, y
)定義的矩形。
實現此目標的最佳方法是什么?
了解到將使用網格交點作為中心點繪制填充區域后,我們有了
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
,並且在第一個for
循環中創建的列表只是plt.fill
可能繪制的矩形角的x , y坐標。
效率說明
如果必須繪制幾百個矩形,上面的簡單方法是可以的,如果進入數萬個矩形,我們可能想使用enumerate
數據點,如果需要,則構造x , y列表並繪制矩形快速運行,或者甚至為了提高性能,創建一個Rectangle
補丁,將其放入PatchCollection
並在完成data
循環后使用ax.add_collection
方法-Matplotlib文檔中提供了一個示例 ,可以很容易地適應范圍和另一個例子是我的新答案。
根據此示例 使用imshow()來使用alpha
。
我正在使用@BM給定的set_ticks代碼
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])
您可以使用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)
在另一個答案中,我提到可以使用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()
這就是結果
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.