如何找到 scipy.stats.binned_statistic_dd() 返回的给定 bin 编号的 bin 边缘?

How to find bin edges of given bin number returned by scipy.stats.binned_statistic_dd()?

我有一个 Nx3 阵列 mm。函数调用

c,edg,idx = scipy.stats.binned_statistic_dd(mm,[], statistic='count',bins=(30,20,10),rg=((3,5),(2,8),(4,6)))

returns idx,这是一个一维整数数组,表示 mm 的每个元素所在的 bin ,并且 edg 是包含 bin edges

的 3 个数组的列表

我需要的是根据 idx 中的 binnumber 找到给定 bin 的 bin 边缘。例如,给定 idx=[24,153,...,72] 我想找到 bin 153 的边缘,即该 bin 落在 edg。当然我可以通过 mm[153] 找到 bin 153 中的元素,但不能找到边缘。

为了清楚起见,我发布了这个 Nx3 案例。实际上,我正在寻找 NxD 案例的解决方案。

首先熟悉 np.unravel_index 会有所帮助。它将 "flat index"(即 binnumber!)转换为坐标元组。您可以将平面索引视为 arr.ravel() 的索引,将坐标元组视为 arr 的索引。例如,如果在下图中我们将数字 0、1、2、3、4、5 视为 bin 编号:

   | 0 | 1 | 2 |
---+---+---+---|
 0 | 0 | 1 | 2 |
 1 | 3 | 4 | 5 |
   +---+---+---|

然后 np.unravel_index(4, (2,3))

In [65]: np.unravel_index(4, (2,3))
Out[65]: (1, 1)

等于 (1,1) 因为形状数组 (2,3) 中的第 4 个 bin 编号具有坐标 (1,1).

那好吧。接下来,我们需要知道在内部 scipy.stats.binned_statistic_dd 给给定的 bin 边缘添加两条边缘来处理离群值:

bin_edges = [np.r_[-np.inf, edge, np.inf] for edge in bin_edges]

所以bin号对应的边缘坐标由

给出
edge_index = np.unravel_index(binnumber, [len(edge)-1 for edge in bin_edges])

(我们使用len(edge)-1是因为数组轴的形状比 边数。)


例如:

import itertools as IT
import numpy as np
import scipy.stats as stats

sample = np.array(list(IT.product(np.arange(5)-0.5, 
                                  np.arange(5)*10-5, 
                                  np.arange(5)*100-50)))
bins = [np.arange(4),
        np.arange(4)*10,
        np.arange(4)*100]

statistic, bin_edges, binnumber = stats.binned_statistic_dd(
    sample=sample, values=sample, statistic='count', 
    bins=bins, 
    range=[(0,100)]*3)

bin_edges = [np.r_[-np.inf, edge, np.inf] for edge in bin_edges]
edge_index = np.unravel_index(binnumber, [len(edge)-1 for edge in bin_edges])


for samp, idx in zip(sample, zip(*edge_index)):
    vert = [edge[i] for i, edge in zip(idx, bin_edges)]
    print('{} goes in bin with left-most corner: {}'.format(samp, vert))

产量

[ -0.5  -5.  -50. ] goes in bin with left-most corner: [-inf, -inf, -inf]
[ -0.5  -5.   50. ] goes in bin with left-most corner: [-inf, -inf, 0.0]
[  -0.5   -5.   150. ] goes in bin with left-most corner: [-inf, -inf, 100.0]
[  -0.5   -5.   250. ] goes in bin with left-most corner: [-inf, -inf, 200.0]
...