【问题标题】:Different considerations when defining 3D bins vs 1D bins for a histogram?为直方图定义 3D bin 与 1D bin 时的不同注意事项?
【发布时间】:2021-03-16 22:58:16
【问题描述】:

我正在尝试为我拥有的一些数据创建一个 3D 直方图,但我认为我定义 bin 的方式一定有问题,因为我得到了很多空的边缘直方图。以下是我如何创建直方图以及如何检查值--

# Hard boundaries for the cube 
param1_range = [0, 6]
param2_range = [-2, +0.5]
param3_range = [0, 2]

d_param1 = 0.5
param1_bins = np.arange(param1_range[0], param1_range[1], d_param1)
N_param1_bins = len(d_param1) - 1

d_param2 = 0.5
param2_bins = np.arange(param2_range[0], param2_range[1], d_param2)
N_param2_bins = len(d_param2) - 1

d_param3 = 0.25
param3_bins = np.arange(param3_range[0], param3_range[1], d_param3)
N_param3_bins = len(d_param3) - 1


empty_param1, empty_param2, empty_param3 = 0, 0, 0 
cube_full = np.zeros((Nobs, N_param1_bins, N_param2_bins, N_param3_bins))
for i in range(Nobs):
    tmp = np.vstack((param1_data[i,:], param2_data[i,:], param3_data[i,:])).T
    hist, _ = np.histogramdd(tmp[:,:],
                             bins=[param1_bins, param2_bins, param3_bins], 
                             density=True)
    cube_full[i,:,:,:] = hist

    if np.all(hist[:,0,0] == 0.):
              empty_param1 = empty_param1 + 1
    if np.all(hist[0,:,0] == 0.):
              empty_param2 = empty_param2 + 1
    if np.all(hist[0,0,:] == 0.):
              empty_param3 = empty_param3 + 1

print(empty_param1/Nobs, empty_param2/Nobs, empty_param3/Nobs)

“param1”的边缘直方图大约有一半是空的,“param2”和“param3”几乎都是空的。

我通过查看数据确定了参数范围。我还使用这些相同的范围为不同的参数创建了 1D 直方图,并且不会像我尝试制作 3D 直方图时那样得到空箱。在定义 3D bin 与 1D bin 时,是否还有一些我遗漏的额外注意事项?

【问题讨论】:

  • 您说的是“边际直方图”,第一个 np.all 询问“param2
  • 您介意解释一下第一个 np.all 选择 param2
  • hist[:,0:0] 将包含 Y 和 Z 坐标进入第零个 bin 的所有点。 Y 的第零个 bin 是 -2 到 -1.5,Z 的第零个 bin 是 0 到 0.25。如果没有 -2
  • hist[0,0,0] 包含 X hist[1,0,0] 包含 0.5
  • 好的,谢谢你的解释。我一定是误解了“hist”的数据结构。我要做的是选择沿不同轴的一维直方图(我的意思是“边际”)。你有什么建议吗?而且,只是为了检查,我试图用 histogramdd 做的是使用 param123_ranges 定义 3D 箱并获得网格点上的幅度。这是 histogramdd 实际上在做什么?

标签: python numpy multidimensional-array histogram


【解决方案1】:

我在这里解释,但从 cmets,我认为你想要的是这样的:

    sum1 = np.sum(hist, (1,2))
    if np.all(sum1) == 0:
        empty_param1 += 1
    sum2 = np.sum(hist, (0,2))
    sum3 = np.sum(hist, (0,1))

这实质上是从 3D 数据生成 1D 直方图。如果我仍然没有达到目标,也许您可​​以提供一个使用较小矩阵的示例。

例子:

>>> x = np.arange(125).reshape((5,5,5))
>>> x
array([[[  0,   1,   2,   3,   4],
        [  5,   6,   7,   8,   9],
        [ 10,  11,  12,  13,  14],
        [ 15,  16,  17,  18,  19],
        [ 20,  21,  22,  23,  24]],

       [[ 25,  26,  27,  28,  29],
        [ 30,  31,  32,  33,  34],
        [ 35,  36,  37,  38,  39],
        [ 40,  41,  42,  43,  44],
        [ 45,  46,  47,  48,  49]],

       [[ 50,  51,  52,  53,  54],
        [ 55,  56,  57,  58,  59],
        [ 60,  61,  62,  63,  64],
        [ 65,  66,  67,  68,  69],
        [ 70,  71,  72,  73,  74]],

       [[ 75,  76,  77,  78,  79],
        [ 80,  81,  82,  83,  84],
        [ 85,  86,  87,  88,  89],
        [ 90,  91,  92,  93,  94],
        [ 95,  96,  97,  98,  99]],

       [[100, 101, 102, 103, 104],
        [105, 106, 107, 108, 109],
        [110, 111, 112, 113, 114],
        [115, 116, 117, 118, 119],
        [120, 121, 122, 123, 124]]])
>>> np.sum(x,(1,2))
array([ 300,  925, 1550, 2175, 2800])
>>> np.sum(x,(0,2))
array([1300, 1425, 1550, 1675, 1800])
>>> np.sum(x,(0,1))
array([1500, 1525, 1550, 1575, 1600])
>>>

【讨论】:

  • 谢谢!这就是我想要的,看起来我定义网格的方式并没有错!
  • 如果你允许我有点刻薄,你最终得到的结果与我上面建议的一维直方图完全一样......
  • 我实际上不会使用 1D 直方图,我需要 3D 网格上的数据幅度。但我必须对分箱数据进行一些(不完全是,但您可以将其视为)单位转换。当我最初尝试这样做时,我得到了很多垃圾,因为我的 ndarray 切片是空的。这就是为什么我认为我的网格定义可能有问题但你证明我的切片是错误的。所以,再次感谢!
猜你喜欢
  • 2021-09-03
  • 2020-10-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多