如何解决标准化2D直方图
我有一个二维直方图h1,其x轴为var1,y轴为var2,是根据dataframe
绘制的。我已经在c ++中对它进行了标准化,但是现在需要在python中做同样的事情,并且正在为获取和设置bin内容而苦苦挣扎。
该想法是消除分布的一个部分中发生的事件多于另一部分的影响,而只保留var1
和var2
之间的相关性。
c ++中的工作代码:
double norm = h1->GetEntries()/h1->GetNbinsX();
int nbins = h1->GetNbinsX();
for(int i = 1; i< nbins+1; i++)
{
double nevents = 0.;
for(int iy = 1; iy< h1->GetNbinsY()+1; iy++)
{
float bincont = h1->GetBinContent(i,iy);
nevents+=bincont;
}
for(int iy = 1; iy< h1->GetNbinsY()+1; iy++)
{
float bincont = h1->GetBinContent(i,iy);
float fact = norm/nevents;
float value = bincont*fact;
h1->SetBinContent(i,iy,value);
}
}
尝试使用python中的代码:
plt.hist2d(var1,var2,bins=(11100,1030),cmap=plt.cm.BuPu)
norm = 10
for i in var1:
nevents = 0.
for j in var2:
plt.GetBinContent(i,j)
nevents+=bincont
for j in var2:
plt.GetBinContent(i,j)
fact = norm/nevents
value = bincont*fact
plt.SetBinContent(i,j,value)
在@JohanC的帮助下进行编辑:
问题已解决。确保规范化时没有nan-s,因为与它们打交道总是很痛苦的。
解决方法
要操作垃圾箱的内容,您可以先计算它们,更改它们,然后再绘制图。
plt.hist2d()
返回两个方向上的bin内容(一个2D矩阵)以及bin边缘。为了获得相同的信息而不作图,np.histogram2d()
返回完全相同的值。然后,可以通过plt.pcolormesh()
绘制结果。
由于某种原因,返回的矩阵将被转置。因此,第一步是再次转置它。
要计算2D数组的总和并进行乘法和除法,numpy具有一些强大的数组和broadcasting操作。 C ++中的双循环只是numpy中的一个操作:hist *= norm / hist.sum(axis=0,keepdims=True)
。由于分母可以为零,因此可以消除警告(结果将是NaN
s和Inf
s在作图时被忽略)。
这是一些演示代码。请注意,使用bins=(11100,1030)
非常大。下面的代码使用更小的值。
from matplotlib import pyplot as plt
import numpy as np
N = 1000000
var1 = np.concatenate([np.random.uniform(0,20,size=9 * N // 10),np.random.normal(10,1,size=N // 10)])
var2 = var1 * 0.1 + np.random.normal(size=N)
fig,(ax1,ax2) = plt.subplots(ncols=2,figsize=(12,4))
norm = 10
binsX = 200
binsY = 100
ax1.hist2d(var1,var2,bins=(binsX,binsY),cmap='BuPu')
ax1.set_title('regular 2d histogram')
hist,xedges,yedges = np.histogram2d(var1,binsY))
hist = hist.T
with np.errstate(divide='ignore',invalid='ignore'): # suppress division by zero warnings
hist *= norm / hist.sum(axis=0,keepdims=True)
ax2.pcolormesh(xedges,yedges,hist,cmap='BuPu')
ax2.set_title('normalized columns')
plt.show()
PS:关于hist *= norm / hist.sum(axis=0,keepdims=True)
:
-
hist.sum(axis=0,keepdims=True)
创建一个新矩阵(命名为s
),其中每个h[i,j]
的元素都替换为所有i
上的元素,因此s[i,j] = sum([h[k,j] for k in range(0,N)])
。如果没有keepdims=True
,则将仅使用总和创建一维数组。 -
hist *= norm / s
像i,j
一样在所有h[i,j]=h[i,j]*norm/s[i,j]
上创建一个循环。除以零会在将零除以零时创建NaN
,而将另一个数除以零会创建inf
。pcolormesh
将忽略这些值。
您也可以执行nan_to_num()
:
hist = np.nan_to_num(hist,nan=0,posinf=0,neginf=0)
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。