Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/arrays/13.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Arrays 将此字符串解析为numpy数组的最快方法_Arrays_Performance_Numpy_Numba - Fatal编程技术网

Arrays 将此字符串解析为numpy数组的最快方法

Arrays 将此字符串解析为numpy数组的最快方法,arrays,performance,numpy,numba,Arrays,Performance,Numpy,Numba,我们必须执行以下操作大约400000次,因此我正在寻找最有效的解决方案。我尝试过几种方法,但我很好奇是否有更好的方法:) 数据示例 我们可以使用以下代码生成一个示例测试集 random.seed(10) np.random.seed(10) def test_str(): n = 10000000 arr = np.random.randint(10000, size=n) sign = np.random.choice(['+','-'], size=n)

我们必须执行以下操作大约400000次,因此我正在寻找最有效的解决方案。我尝试过几种方法,但我很好奇是否有更好的方法:)


数据示例 我们可以使用以下代码生成一个示例测试集
random.seed(10)
np.random.seed(10)
def test_str():
    n = 10000000
    arr  = np.random.randint(10000, size=n)
    sign = np.random.choice(['+','-'], size=n)
    return 'ID1' + '\t' + ' '.join(["{}{}".format(a,b) for a,b in zip(arr, sign)])
看起来像是
ID1\t7688+737+677+1508-9251-…

它所涉及的代码:) 从中复制代码(p.s.在那里运行它会给我一个
打字机错误
,而它在我的机器上运行得很好),或者只查看下面的功能

一般功能
从这一点来看,但是基于@armamut-answer,这可能会给Numba带来很多开销,使得原生Numpy显然更快

@nb.jit(nopython=True)
    def str_to_int(s):
        final_index, result = len(s) - 1, 0
        for i,v in enumerate(s):
            result += (ord(v) - 48) * (10 ** (final_index - i))
        return result
方法1

@nb.jit(nopython=True)
def process_number(numb, identifier, i):
    sign = 1 if numb[-1] == '+' else -1
    return str_to_int(numb[:-1]), sign, i, identifier
    
@nb.jit(nopython=True)
def expand1(data):
    identifier, l = data.split('\t')
    identifier = str_to_int(identifier[-1])
    numbers = l.split()
    # init emtpy numpy array
    arr = np.empty(shape = (len(numbers), 4), dtype = np.int64)
    # Fill array    
    for i, numb in enumerate(numbers):
        arr[i,:] = process_number(numb, identifier, i)
    return arr
方法2

@nb.jit(nopython=True)
def expand2(data):
    identifier, l = data.split('\t')
    
    identifier = str_to_int(identifier[-1])
    numbers = l.split()
    size = len(numbers)
    
    numbs = [ str_to_int(numb[:-1]) for numb in numbers ]
    signs = [ 1 if numb[:-1] =='+' else -1 for numb in numbers ]
    
    arr = np.empty(shape = (size, 4), dtype = np.int64)
    arr[:,0] = numbs
    arr[:,1] = signs
    arr[:,2] = np.arange(0, size)
    arr[:,3] = np.repeat(identifier, size)
    return arr
方法3

@nb.jit(nopython=True)
def expand3(data):
    identifier, l = data.split('\t')
    identifier = str_to_int(identifier[-1])
    numbers = l.split()
    arr = np.empty(shape = (len(numbers), 4), dtype = np.int64)
    for i, numb in enumerate(numbers):
        arr[i,:] = str_to_int(numb[:-1]), 1 if numb[:-1] =='+' else -1, i, identifier
    return arr
回答方法

def expand4(t):
    identifier, l = t.split('\t')
    identifier = np.int(identifier[-1])
    numbers = np.array([np.int(k[:-1]) for k in l.split(' ')])
    signs = np.array([(k[-1] == '+') for k in l.split(' ')]) * 2 - 1

    N = len(numbers)
    arr = np.empty(shape = (N, 4), dtype = np.int64)
    arr[:, 0] = numbers
    arr[:, 1] = signs
    arr[:, 2] = identifier
    arr[:, 3] = np.arange(N)
    return arr
测试结果

Expand 1
72.7 ms ± 177 ms per loop (mean ± std. dev. of 7 runs, 5 loops each)
Expand 2
27.9 ms ± 67.1 ms per loop (mean ± std. dev. of 7 runs, 5 loops each)
Expand 3
8.81 ms ± 20.3 ms per loop (mean ± std. dev. of 7 runs, 5 loops each)
Expand 4 ANSWER 1
429 µs ± 63.4 µs per loop (mean ± std. dev. of 7 runs, 5 loops each)


我无法复制您的代码,因为我还得到了numba的“ord”未实现错误

但是你为什么要用麻木?您的str_to_int操作似乎非常昂贵,并且对于向量操作等而言未优化。为什么不(没有numba):

def扩展(t):
标识符,l=t.split('\t')
标识符=np.int(标识符[-1])
numbers=np.array([np.int(k[:-1]),表示l.split(“”)中的k)
符号=np.数组([(k[-1]='+')表示l.split中的k('')*2-1
N=len(数字)
arr=np.empty(shape=(N,4),dtype=np.int64)
arr[:,0]=数字
arr[:,1]=符号
arr[:,2]=标识符
arr[:,3]=np.arange(N)
返回arr
t=测试_str()
%时间扩展(t)
>>>
每个回路1.01 ms±121µs(7次运行的平均值±标准偏差,每个1000个回路)

在代码中
expand1
不会产生与
expand2
expand3
相同的结果。此外,您还需要numpy的种子(并在所有实验中使用相同的
test\u str()
)来获得确定性和相同的结果。@DavidM。谢谢我在
process\u number
函数中切换了
identifier
sign
,并在Google Colab代码中添加了种子,您还需要设置
s=test\u str()
,然后将其传递给
expand
函数,否则每个函数将处理不同的数据。@DavidM。哎呀。。再次感谢!如果您显示了一个示例字符串,例如:
'ID1\t7688+737+677+1508-9251-'
nice,那就太好了!使用
布尔*2-1
:)还有很酷的技巧。这确实比使用Numba更快,可能是因为
str\u to\u int
函数。[但是你为什么要使用numba?]通常我更喜欢使用numba,因为它在第一次运行后跳过了编译过程,大大加快了速度。是的,你说得对。我想知道使用麻木是否有特殊的原因。如果没有严格的必要,没关系:)顺便说一句,如果你接受这个解决方案,我会很高兴的,谢谢!是的,我会等一会儿,看看其他人有没有想法