优化的功能将数组分成垃圾箱

时间:2015-12-07 12:33:44

标签: python arrays algorithm sorting

我在python中创建一个函数,根据x数组将两个数组x和y分成预定数量的bin。我已经制作了一个可行的算法,但它确实很慢。这是(显然)有效的代码:

def sepbin(x, y, classes_number=100, log_scale=True):
    if log_scale:
        if x[0]<=0:
            print 'Warning: zero value in array about to be log-scaled. Ignoring it.'
            x=x[1:]
            y=y[1:]
        bins=np.logspace(np.log(x[0]), np.log(x[-1]), classes_number+1, base=np.e)
    else:
        bins=np.linspace(x[0], x[-1], classes_number+1)
    ybins=[[] for i in range(classes_number)]
    xbins=[[] for i in range(classes_number)]
    for xx, yy in zip(x,y):
        i=0
        while i<classes_number:
            if ((xx>=bins[i]) and (xx<bins[i+1])):
                ybins[i].append(yy)
                xbins[i].append(xx)
                break
            elif (i==(classes_number-1)) and xx==bins[-1]:
                ybins[i].append(yy)
                xbins[i].append(xx)
                break
            else:
                i+=1
    xsm = np.array(map(np.mean, xbins))
    ysm = np.array(map(np.mean, ybins))
    return xsm, ysm

正如您所看到的,我想为对数缩放和线性缩放的输出腾出空间,因此我不能假设线性间隔的分档。我只假设数据按新月或递减顺序排列(但这很容易概括)。

显然,代码运行良好,但由于我希望使用非常大的数据集(100000多个元素),我认为应该优化它。我有什么办法可以在这里使用numpyscipy来加快速度吗?令我感到惊讶的是,我在numpy中找不到分箱功能!所以也许我看起来不对。

谢谢。

1 个答案:

答案 0 :(得分:0)

您可以使用numpy的索引来查找每个bin中xy的元素,而不是您的O(nk)双循环:

def sepbin2(x, y, classes_number=100, log_scale=True):
    if log_scale:
        if x[0]<=0:
            print 'Warning: zero value in array about to be log-scaled. Ignoring it.'
            x=x[1:]
            y=y[1:]
        bins=np.logspace(np.log(x[0]), np.log(x[-1]), classes_number+1, base=np.e)
    else:
        bins=np.linspace(x[0], x[-1], classes_number+1)
    # pre-allocate return values
    xsm = np.zeros(classes_number)
    ysm = np.zeros(classes_number)
    # find elements in each bin
    for i in range(classes_number):
        if i == classes_number - 1:
            sel = bins[i] <= x
        else:
            sel = (bins[i] <= x) & (x < bins[i+1])
        xsm[i] = np.mean(x[sel])
        ysm[i] = np.mean(y[sel])
    return xsm, ysm

在我的测试中,这个函数似乎提供与你编写的输出完全相同的输出。我使用稍微不同的代码来选择最后一个bin(我不确定你为什么写xx==bins[-1])。

sepbin2速度要快得多。使用100K数据点:

x = np.random.random((100000,))
x.sort()
y = np.random.random((100000,))

我们得到:

In [1]: %timeit sepbin(x, y, classes_number=100)
1 loops, best of 3: 5.21 s per loop
In [2]: %timeit sepbin2(x, y, classes_number=100)
100 loops, best of 3: 18.9 ms per loop