如何提高Python(Numpy)中数组切片和操作的效率?

时间:2021-03-29 16:52:57

标签: python numpy numpy-ndarray

我有一个包含 N 个数组的数据集,每个数组可能有固定或可变长度。我将从数据集中提取一个窗口并计算给定数字的出现次数。为简单起见,我假设每个数组包含 90 个数字。模型会在每个数组上随机选取一个位置,从该位置开始提取M个连续的数字作为窗口条,这样就得到了总共N条。我假设每个条带具有相同的大小,因此所有 N 个条带构成一个视图(窗口)。我有一个 C++ 代码来执行这项工作并且工作得很好,对于 5x90 的数据集,重复窗口采样 1000000 次,每 10,000 次迭代完成大约需要 0.002 秒。我正在尝试将 C++ 移植到 Python,以便我可以使用强大的数据框 (Pandas) 和其他工具进行相关分析。经过一些研究,似乎 Numpy 数组是数据数组的一个很好的表示,但由于每个数组的大小各不相同,我需要将所有数组扭曲成一个列表。我在下面显示的代码(删除了大部分不相关的代码)

import numpy as np
import random
import time

class dataSource:
    _data = None
    _NCOLS = 0
    _NROWS = 0

    # NCOLS, NROWS is the dimension of a window (view) of the data
    # _data is a list of NCOLS Numpy array, each array carry 90 numbers
    def __init__(self, NCOLS, NROWS):
        # assuming each array has 90 numbers for this exmaple, it could be varied in actual case
        src = [[1]*90]*NCOLS # just assume all numbers in the array to be 1 for this example
        self._data = [np.array(cc) for cc in src]
        self._NCOLS = NCOLS
        self._NROWS = NROWS

    def extractView(self, view):
        pos = [random.randint(0, len(cc)-1-self._NROWS) for cc in self._data]
        for col in range(len(self._data)):
        view[:, col] = self._data[col][pos[col]:pos[col]+self._NROWS]

class dataView:
    _NCOLS = 0
    _NROWS = 0
    _view = None

    def __init__(self, NCOLS, NROWS):
        self._NCOLS = NCOLS
        self._NROWS = NROWS
        self._view = np.zeros([self._NROWS, self._NCOLS], order='F')

    def __setitem__(self, key, value):
        self._view[key] = value

    def count(self, elem):
        return np.count_nonzero(self._view==elem)

if __name__ == '__main__':
    ds = dataSource(5, 3)
    dv = dataView(5, 3)
    batchCount, totalTime, startTime = 1, 0, time.process_time()
    for n in range(10000000):
        if ((n+1)%10000==0):
            dt = time.process_time() - startTime
            totalTime += dt
            print(totalTime / batchCount, ' ', dt)
            batchCount += 1
            startTime = time.process_time()

        ds.extractView(dv)
        cnt = dv.count(1) # this could then be used for other analysis, dv may be used by other functions

在 Python 3.8.8 中运行此代码显示代码每 10,000 次迭代需要 0.23 秒才能完成。 Python 代码比 C++ 慢大约 100 倍。在实际情况下,数据源最多可以有 50 个数组,每个数组可能有 50 到 500 个数字,因此 Python 中的运行时间可能会更长。在真实数据中应用C++代码,完成所有迭代大约需要5个小时,根据上面的估算,在Python中做同样的工作需要500个小时。我知道 Python 中可能存在一些限制,因此很难提高速度,但是如果我能做任何事情来优化我的代码以减少时间(甚至 10%)都会有很大帮助。

0 个答案:

没有答案