【问题标题】:binning data in python with scipy/numpy使用 scipy/numpy 在 python 中分箱数据
【发布时间】:2011-09-04 00:50:11
【问题描述】:

有没有一种更有效的方法来对预先指定的 bin 中的数组取平均值?例如,我有一个数字数组和一个对应于该数组中 bin 开始和结束位置的数组,我只想取这些 bin 中的平均值?我有下面的代码,但我想知道如何减少和改进它。谢谢。

from scipy import *
from numpy import *

def get_bin_mean(a, b_start, b_end):
    ind_upper = nonzero(a >= b_start)[0]
    a_upper = a[ind_upper]
    a_range = a_upper[nonzero(a_upper < b_end)[0]]
    mean_val = mean(a_range)
    return mean_val


data = rand(100)
bins = linspace(0, 1, 10)
binned_data = []

n = 0
for n in range(0, len(bins)-1):
    b_start = bins[n]
    b_end = bins[n+1]
    binned_data.append(get_bin_mean(data, b_start, b_end))

print binned_data

【问题讨论】:

    标签: python numpy scipy scientific-computing


    【解决方案1】:

    使用numpy.digitize() 可能更快更容易:

    import numpy
    data = numpy.random.random(100)
    bins = numpy.linspace(0, 1, 10)
    digitized = numpy.digitize(data, bins)
    bin_means = [data[digitized == i].mean() for i in range(1, len(bins))]
    

    另一种方法是使用numpy.histogram()

    bin_means = (numpy.histogram(data, bins, weights=data)[0] /
                 numpy.histogram(data, bins)[0])
    

    自己试试哪个更快... :)

    【讨论】:

    • 我没有看到差异——哪个更快?
    • @user:我不知道哪个对您的数据和参数更快。这两种方法都应该比你的更快,我希望histogram() 方法对于大量垃圾箱来说更快。但你必须自我介绍,我不能为你做这件事。
    【解决方案2】:

    Scipy (>=0.11) 函数 scipy.stats.binned_statistic 专门解决了上述问题。

    对于与先前答案相同的示例,Scipy 解决方案将是

    import numpy as np
    from scipy.stats import binned_statistic
    
    data = np.random.rand(100)
    bin_means = binned_statistic(data, data, bins=10, range=(0, 1))[0]
    

    【讨论】:

      【解决方案3】:

      不知道为什么这个线程会死;但这是 2014 年批准的答案,应该更快:

      import numpy as np
      
      data = np.random.rand(100)
      bins = 10
      slices = np.linspace(0, 100, bins+1, True).astype(np.int)
      counts = np.diff(slices)
      
      mean = np.add.reduceat(data, slices[:-1]) / counts
      print mean
      

      【讨论】:

      • 您正在回答不同的问题。例如你的mean[0] = np.mean(data[0:10]),而正确答案应该是np.mean(data[data &lt; 10])
      【解决方案4】:

      numpy_indexed 包(免责声明:我是它的作者)包含有效执行此类操作的功能:

      import numpy_indexed as npi
      print(npi.group_by(np.digitize(data, bins)).mean(data))
      

      这与我之前发布的解决方案基本相同;但现在包装在一个漂亮的界面中,包含测试和所有内容:)

      【讨论】:

        【解决方案5】:

        我想补充一下,也回答find mean bin values using histogram2d python这个问题,scipy也有专门为compute a bidimensional binned statistic for one or more sets of data设计的功能

        import numpy as np
        from scipy.stats import binned_statistic_2d
        
        x = np.random.rand(100)
        y = np.random.rand(100)
        values = np.random.rand(100)
        bin_means = binned_statistic_2d(x, y, values, bins=10).statistic
        

        函数scipy.stats.binned_statistic_dd 是该函数对高维数据集的泛化

        【讨论】:

          【解决方案6】:

          另一种选择是使用 ufunc.at。此方法在指定索引处就地应用所需操作。 我们可以使用 searchsorted 方法获取每个数据点的 bin 位置。 然后我们可以使用 at 将直方图在 bin_indexes 给定的索引处的位置增加 1,每次遇到 bin_indexes 处的索引时。

          np.random.seed(1)
          data = np.random.random(100) * 100
          bins = np.linspace(0, 100, 10)
          
          histogram = np.zeros_like(bins)
          
          bin_indexes = np.searchsorted(bins, data)
          np.add.at(histogram, bin_indexes, 1)
          

          【讨论】:

            猜你喜欢
            • 2011-02-14
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2022-01-17
            • 2014-09-22
            • 2018-04-15
            • 2011-02-28
            • 2017-10-25
            相关资源
            最近更新 更多