[英]Python: Creating a 2D histogram from a numpy matrix
我是python的新手。
我有一個numpy矩陣,尺寸為42x42,其值在0-996范圍內。 我想用這個數據創建一個2D直方圖。 我一直在看教程,但他們似乎都展示了如何從隨機數據而不是numpy矩陣創建2D直方圖。
到目前為止,我已導入:
import numpy as np
import matplotlib.pyplot as plt
from matplotlib import colors
我不確定這些是否是正確的導入,我只是想從我看到的教程中學到一些東西。
我有numpy矩陣M
其中包含所有值(如上所述)。 最后,我希望它看起來像這樣:
顯然,我的數據會有所不同,所以我的情節應該看起來不同。 任何人都可以幫我一把嗎?
編輯:為了我的目的,下面的Hooked的例子,使用matshow,正是我正在尋找的。
如果你有來自計數的原始數據,你可以使用plt.hexbin
為你創建圖(恕我直言這比方格更好):改編自hexbin
的例子:
import numpy as np
import matplotlib.pyplot as plt
n = 100000
x = np.random.standard_normal(n)
y = 2.0 + 3.0 * x + 4.0 * np.random.standard_normal(n)
plt.hexbin(x,y)
plt.show()
如果你已經提到了矩陣中的Z值,只需使用plt.imshow
或plt.matshow
:
XB = np.linspace(-1,1,20)
YB = np.linspace(-1,1,20)
X,Y = np.meshgrid(XB,YB)
Z = np.exp(-(X**2+Y**2))
plt.imshow(Z,interpolation='none')
如果您不僅有2D直方圖矩陣而且還有基礎(x, y)
數據,那么您可以根據2D直方圖中的分箱計數值制作(x, y)
點的散點圖並為每個點着色矩陣:
import numpy as np
import matplotlib.pyplot as plt
n = 10000
x = np.random.standard_normal(n)
y = 2.0 + 3.0 * x + 4.0 * np.random.standard_normal(n)
xedges, yedges = np.linspace(-4, 4, 42), np.linspace(-25, 25, 42)
hist, xedges, yedges = np.histogram2d(x, y, (xedges, yedges))
xidx = np.clip(np.digitize(x, xedges), 0, hist.shape[0]-1)
yidx = np.clip(np.digitize(y, yedges), 0, hist.shape[1]-1)
c = hist[xidx, yidx]
plt.scatter(x, y, c=c)
plt.show()
@ unutbu的答案包含一個錯誤: xidx
和yidx
以錯誤的方式計算(至少在我的數據樣本上)。 正確的方法應該是:
xidx = np.clip(np.digitize(x, xedges) - 1, 0, hist.shape[0] - 1)
yidx = np.clip(np.digitize(y, yedges) - 1, 0, hist.shape[1] - 1)
由於我們感興趣的np.digitize
的返回維度介於1
和len(xedges) - 1
,但c = hist[xidx, yidx]
需要0
和hist.shape - 1
之間的索引。
以下是結果的比較。 你可以看到你得到相似但不一樣的結果。
import numpy as np
import matplotlib.pyplot as plt
fig = plt.figure()
ax1 = fig.add_subplot(211)
ax2 = fig.add_subplot(212)
n = 10000
x = np.random.standard_normal(n)
y = 2.0 + 3.0 * x + 4.0 * np.random.standard_normal(n)
xedges, yedges = np.linspace(-4, 4, 42), np.linspace(-25, 25, 42)
hist, xedges, yedges = np.histogram2d(x, y, (xedges, yedges))
xidx = np.clip(np.digitize(x, xedges), 0, hist.shape[0] - 1)
yidx = np.clip(np.digitize(y, yedges), 0, hist.shape[1] - 1)
c = hist[xidx, yidx]
old = ax1.scatter(x, y, c=c, cmap='jet')
xidx = np.clip(np.digitize(x, xedges) - 1, 0, hist.shape[0] - 1)
yidx = np.clip(np.digitize(y, yedges) - 1, 0, hist.shape[1] - 1)
c = hist[xidx, yidx]
new = ax2.scatter(x, y, c=c, cmap='jet')
plt.show()
我是'散射直方圖'的忠實粉絲,但我不認為其他解決方案完全正確。 這是一個實現它們的函數 。 與其他解決方案相比,此函數的主要優點是它通過hist數據對點進行排序(請參閱mode
參數)。 這意味着結果看起來更像傳統的直方圖(即,您不會在不同的箱中得到標記的混亂重疊)。
MCVE這個數字(使用我的功能 ):
import numpy as np
import matplotlib.pyplot as plt
from hist_scatter import scatter_hist2d
fig = plt.figure(figsize=[5, 4])
ax = plt.gca()
x = randgen.randn(npoint)
y = 2 + 3 * x + 4 * randgen.randn(npoint)
scat = scatter_hist2d(x, y,
bins=[np.linspace(-4, 4, 42),
np.linspace(-25, 25, 42)],
s=5,
cmap=plt.get_cmap('viridis'))
ax.axhline(0, color='k', linestyle='--', zorder=3, linewidth=0.5)
ax.axvline(0, color='k', linestyle='--', zorder=3, linewidth=0.5)
plt.colorbar(scat)
這種方法的主要缺點是最密集區域中的點與較低密度區域中的點重疊,導致每個箱區域的某種程度的錯誤表示。 我花了很多時間探索兩種方法來解決這個問題:
1)使用較小的標記用於較高密度的箱
2)對每個箱子應用“剪裁”掩碼
第一個給出的結果太瘋狂了。 第二個看起來不錯 - 特別是如果你只剪輯有大約20點的垃圾箱 - 但它非常慢 ( 這個數字花了大約一分鍾)。
所以,最終我決定通過仔細選擇標記大小和bin大小( s
和bins
),你可以獲得視覺上令人愉悅的結果,而且在誤報數據方面也不會太糟糕。 畢竟,這些2D直方圖通常旨在成為對基礎數據的視覺輔助,而不是對其的嚴格定量表示。 因此,我認為這種方法遠遠優於“傳統2D直方圖”(例如, plt.hist2d
或plt.hexbin
),我認為如果你找到了這個頁面,你也不是傳統的粉絲(單色) ) 散點圖。
如果我是科學之王,我會確保所有的二維直方圖在剩余的時間里做到這一點。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.