需要帮助为直方图的每个区间加权(缩放)不同的因子
我正在尝试制作一个粒子圆形散布的径向分布直方图,并且想要将这个直方图缩放,使得径向分布表示为每单位面积的粒子数量。
声明: 如果你对我所说的数学内容不感兴趣,可以跳过这一部分:
我将径向分布分成宽度相等的环形区域,从中心向外扩展。所以,在中心,我会有一个半径为a的圆。这个最内层区域的面积是$\pi a^{2}$。
现在,如果我们想知道从半径a到2a的环形区域的面积,我们可以计算 $$ \int_{a}^{2a} 2 \pi r \ dr = 3 \pi a^{2} $$
继续以类似的方式(从2a到3a,3a到4a,等等),我们可以看到面积是这样增加的: $$ 面积 = \pi a^{2}, 3 \pi a^{2}, 5 \pi a^{2}, 7 \pi a^{2}, ... $$
所以,当我为散布的径向分布加权直方图时,从中心向外,每个区间的计数需要加权:第一个区间的计数保持不变,第二个区间的计数要除以3,第三个区间的计数要除以5,依此类推。
所以:这是我尝试写的代码:
import numpy as np
import matplotlib.pyplot as plt
# making random sample of 100000 points between -2.5 and 2.5
y_vec = 5*np.random.random(100000) - 2.5
z_vec = 5*np.random.random(100000) - 2.5
# blank canvasses for the y, z, and radial arrays
y_vec2 = []
z_vec2 = []
R_vec = []
# number of bins I want in the ending histogram
bns = 40
# cutting out the random samplings that aren't in a circular distribution
# and making the radial array
for i in range(0, 100000):
if np.sqrt((y_vec[i]*y_vec[i] + z_vec[i]*z_vec[i])) <= 2.5:
y_vec2.append(y_vec[i])
z_vec2.append(z_vec[i])
R_vec.append(np.sqrt(y_vec[i]*y_vec[i] + z_vec[i]*z_vec[i]))
# setting up the figures and plots
fig, ax = plt.subplots()
fig2, hst = plt.subplots()
# creating a weighting array for the histogram
wghts = []
i = 0
c = 1
# making the weighting array so that each of the bins will be weighted correctly
# (splitting the radial array up evenly in to groups of the size the bins will be
# and weighting them appropriately). I assumed the because the documentation says
# the "weights" array has to be the same size as the "x" initial input, that the
# weights act on each point individually...
while i < bns:
wghts.extend((1/c)*np.ones(len(R_vec)/bns))
c = c + 2
i = i + 1
# Making the plots
ax.scatter(y_vec2, z_vec2)
hst.hist(R_vec, bins = bns, weights = wghts)
# plotting
plt.show()
散点图看起来很好:

但是,径向图表明我在加权上出了问题。它应该在所有环形区域中保持恒定,但实际上是增加的,似乎根本没有加权:

径向分布的杂乱外观让我觉得“hist”操作中的加权函数是对R_vec中的每个成员单独加权,而不是对区间加权。
我该如何按我需要的因子对这些区间进行加权呢?有什么帮助吗?
2 个回答
当你想要绘制某个东西“每单位面积”的时候,就把面积作为你的自变量。这样的话,如果你喜欢的话,还是可以用直方图,但你就不用担心不均匀的分箱或者加权的问题了。
我把你的那行代码替换成了:
hst.hist(R_vec, bins = bns, weights = wghts)
变成了:
hst.hist(np.pi*np.square(R_vec),bins=bns)
你说得对,权重是用来影响每个值的,而不是用来影响区间的。这一点在文档中有说明:
x中的每个值只会对区间计数贡献它对应的权重(而不是1)。
所以,问题的关键在于,在计算权重时,你没有考虑到点的顺序。你是随机生成点的,但权重是按从大到小的顺序生成的。这就导致你没有把正确的权重分配给正确的点。
你应该通过直接根据每个点的半径来计算权重。你似乎想要的做法是把半径分成几个区间,然后反向给权重。与其这样做权重,不如试试下面的方法:
R_vec = np.array(R_vec)
wghts = 1 / (2*(R_vec//(2.5/bns))+1)
这样我得到了正确的结果:
你也可以不通过区间来计算权重,直接用每个点的半径的倒数来给权重,这样也能得到基本相同的结果:
R_vec = np.array(R_vec)
wghts = 1 / R_vec
这样做的好处是,你可以在不重新计算权重的情况下,绘制不同数量的区间直方图。而且,从概念上讲,按每个点距离中心的远近来加权,更合理,而不是看它是否落在某个离散区间的边界上。