簡體   English   中英

Matplotlib:從二進制數據填充

[英]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)坐標,並且不能使用此數據
  • imshowmatshow ,不幸的是,它們會在各處繪制一些顏色。 也就是說,無論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可能繪制的矩形角的xy坐標。


效率說明

如果必須繪制幾百個矩形,上面的簡單方法是可以的,如果進入數萬個矩形,我們可能想使用enumerate數據點,如果需要,則構造xy列表並繪制矩形快速運行,或者甚至為了提高性能,創建一個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解決可能的效率問題,這是此方法的實現。 首先進行初始化,請注意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()                                                                    

這就是結果

在此處輸入圖片說明

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM