Python 二维直方图的归一化
我有一个二维柱状图h1,x轴上有var1,y轴上有var2,这是我从Python 二维直方图的归一化,python,c++,pandas,dataframe,matplotlib,Python,C++,Pandas,Dataframe,Matplotlib,我有一个二维柱状图h1,x轴上有var1,y轴上有var2,这是我从数据帧绘制的。我已经在C++中实现了它的标准化,但是现在需要在Python中做同样的事情,并且在如何获取和设置bin内容方面遇到困难。 这样做的目的是消除分布的一部分中的事件多于另一部分的影响,只保留var1和var2之间的相关性 c++中的工作代码: double norm = h1->GetEntries()/h1->GetNbinsX(); int nbins = h1->GetNbinsX(
数据帧
绘制的。我已经在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);
}
}
来自@JohanC的帮助后编辑:
问题已经解决了。正常化时,请确保没有nan-s,因为处理它们总是一件痛苦的事情。要处理垃圾箱的内容,您可以先计算它们,更改它们,然后再绘制绘图
plt.hist2d()
返回箱子内容(二维矩阵)以及两个方向的箱子边缘。要在不打印的情况下获得相同的信息,np.historogram2d()
返回完全相同的值。然后,可以通过plt.pcolormesh()
绘制结果
由于某种原因,返回的矩阵被转置。因此,第一步是再次转置它
numpy有一些强大的数组和运算功能,可以在2D数组上计算和并进行乘法和除法。C++中的双循环只是NUMPY中的一个操作:<代码> Hist*= NORM/Hist.AUM(轴=0,KeEdidis= true)< /C>。由于分母可以为零,因此可以抑制警告(结果将是打印时忽略的NaN
s和Inf
s)
下面是一些演示代码。请注意,使用bin=(11100130)
非常大。下面的代码使用更小的值
从matplotlib导入pyplot作为plt
将numpy作为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.随机.正常(大小=N)
图(ax1,ax2)=plt.子批次(ncols=2,figsize=(12,4))
标准=10
BINx=200
宾西=100
ax1.hist2d(var1,var2,bins=(binsX,binsY),cmap='BuPu')
ax1.设置标题(“常规二维直方图”)
hist,xedges,yedges=np.histogram2d(var1,var2,bins=(binsX,binsY))
hist=hist.T
使用np.errstate(divide='ignore',invalid='ignore'):#抑制零除警告
hist*=norm/hist.sum(轴=0,keepdims=True)
ax2.pcolormesh(xedges、yedges、hist、cmap='BuPu')
ax2.设置标题(“标准化列”)
plt.show()
PS:Abouthist*=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]表示范围(0,N)])
,则只会创建包含和的1D数组keepdims=True
在所有hist*=norm/s
上创建一个循环,如i,j
。当用零除零时,用零除产生h[i,j]=h[i,j]*norm/s[i,j]
,当用另一个数字除零时,产生NaN
。这些值被inf
忽略pcolormesh
嘿,欢迎来到stack overflow!我注意到python代码中有
var21
,这应该是var1
?您好,Warlax56,您说得对。非常感谢。我编辑:)你好,约翰。非常感谢您的解决方案。它与您的var1和var2示例完美结合。然而,出于某种原因,当我从数据文件输入我的时,它会给我以下错误:RuntimeWarning:在较少的cbook中遇到无效值。\u putmask(xa,xa<0.0,-1)和空的标准化绘图。你知道有什么问题吗?我删除了NAN并用:df=df.dropna()df=df.reset_index(drop=True)重置索引。谢谢。我不知道如何在这里发布图片,所以作为单独的答案发布。我也测试了垃圾箱,现在我来看看其余的。好吧,你是对的,出于某种原因,hist.sum(axis=1)都是NAN,尽管其余的都是预期的。正常化后立即出现错误/警告。零除以零时出现NaN。要查看更多颜色,还可以尝试颜色的lognorm:ax2.pcolormesh(…,norm=matplot.colors.lognorm())
它似乎也不是20以下的区域。我只是不知道这些0来自哪里。在第一个绘图上看到的所有值都很好,我在绘图之前删除了所有可能的NAN。也许我不明白正常化是如何发生的?
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)
hist = np.nan_to_num(hist, nan=0, posinf=0, neginf=0)