【问题标题】:How to find bin edges of given bin number returned by scipy.stats.binned_statistic_dd()?如何找到 scipy.stats.binned_statistic_dd() 返回的给定 bin 编号的 bin 边缘?
【发布时间】:2015-02-26 11:56:59
【问题描述】:

我有一个 Nx3 数组 mm。函数调用

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

返回idx,它是一维整数数组,表示mm的每个元素所在的bin,edg是一个包含 bin 边缘的 3 个数组的列表

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

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

【问题讨论】:

    标签: python numpy scipy binning


    【解决方案1】:

    首先熟悉np.unravel_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]
    ...
    

    【讨论】:

    • 很好的解决方案 unutbu。我找到了 unravel_index() 和 binned_statistic_dd() 的额外垃圾箱,但无法找到完整的解决方案。我通过简单地修改 binned_statistic_dd() 源代码以返回 Ncount 来实现一个不太优雅的解决方案,它为每个输入元素保存每个维度中的 1d bin 编号。但你的方法更简单。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-06-05
    • 1970-01-01
    • 2013-12-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多