Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/php/245.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
Python 将整数字符串列表转换为整数数组的最有效方法_Python_Performance_Numpy - Fatal编程技术网

Python 将整数字符串列表转换为整数数组的最有效方法

Python 将整数字符串列表转换为整数数组的最有效方法,python,performance,numpy,Python,Performance,Numpy,我有一个简单的问题-我需要将一个整数字符串转换为一个整数列表,并将其插入numpy数组 我有可以工作的代码,但如果有更有效的方法,我对它感兴趣。开始的条件是我有一个整数字符串列表(第4行),目标是得到一个用这些整数填充的numpy数组 下面是我使用的代码示例: import numpy as np print("Hello StackOverflow") listOfStringOfINTs = ["123231231231231"]*5 print(listOfStringOfINTs) n

我有一个简单的问题-我需要将一个整数字符串转换为一个整数列表,并将其插入numpy数组

我有可以工作的代码,但如果有更有效的方法,我对它感兴趣。开始的条件是我有一个整数字符串列表(第4行),目标是得到一个用这些整数填充的numpy数组

下面是我使用的代码示例:

import numpy as np
print("Hello StackOverflow")

listOfStringOfINTs = ["123231231231231"]*5
print(listOfStringOfINTs)
numpyVectorOfInts = np.empty([len(listOfStringOfINTs),len(listOfStringOfINTs[0]) ], dtype='int')
for i, IntString in enumerate(listOfStringOfINTs):
    numpyVectorOfInts[i] = list(map(int, IntString))

print(numpyVectorOfInts)

我不确定这在速度上是否更好,但它更简单:

In [68]: np.array([list(astr) for astr in listOfStringOfINTs],int)           
Out[68]: 
array([[1, 2, 3, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1],
       [1, 2, 3, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1],
       [1, 2, 3, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1],
       [1, 2, 3, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1],
       [1, 2, 3, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1]])
list(astr)
将字符串拆分为1个字符串的列表。带有
int
dtype的
np.array
负责转换所有字符串

或者,您可以将所有字符串合并到字符串中,创建列表,然后重塑数组:

np.array(list(''.join(listOfStringOfINTs)),int).reshape(5,-1)

为了好玩,这里有另一种方法:

>>> np.vstack(np.frombuffer(a,dtype=np.uint8)-48 for a in listOfStringOfINTs)
array([[1, 2, 3, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1],
       [1, 2, 3, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1],
       [1, 2, 3, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1],
       [1, 2, 3, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1],
       [1, 2, 3, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1]], dtype=uint8)
此方法依赖于将ASCII字符作为无符号字符读取,然后依赖于数字1-9在ASCII表示中的顺序这一事实。因为数字0表示为48,所以我们只需从所有值中减去48,就可以得到它们作为整数的值

对于小字符串,它实际上并不比@hpaulj的方法快,后者更具可读性:

In [1]: listOfStringOfINTs = ["123231231231231"]*10000

In [2]: %timeit np.vstack(np.frombuffer(a,dtype=np.uint8)-48 for a in listOfStringOfINTs)
10 loops, best of 3: 42.1 ms per loop

In [3]: %timeit np.array([list(astr) for astr in listOfStringOfINTs],int)
10 loops, best of 3: 36.3 ms per loop
但对于较大的字符串,它会产生很大的不同:

In [4]: listOfStringOfINTs = ["123231231231231"*1000]*10000

In [5]: %timeit np.vstack(np.frombuffer(a,dtype=np.uint8)-48 for a in listOfStringOfINTs)
10 loops, best of 3: 115 ms per loop

In [6]: %timeit np.array([list(astr) for astr in listOfStringOfINTs],int)
1 loop, best of 3: 30.4 s per loop

以上所有答案都是正确的,但凭直觉,我最容易理解的是:

    >>> k = [list(x) for x in listOfStringOfINTs ]
    >>> print(np.array(k, dtype=np.int64))
    [[1 2 3 2 3 1 2 3 1 2 3 1 2 3 1]
     [1 2 3 2 3 1 2 3 1 2 3 1 2 3 1]
     [1 2 3 2 3 1 2 3 1 2 3 1 2 3 1]
     [1 2 3 2 3 1 2 3 1 2 3 1 2 3 1]
     [1 2 3 2 3 1 2 3 1 2 3 1 2 3 1]]

利用所有字符串具有相同数量的字符这一事实,我们可以使用带有
view
-

def get_int_ar(a):
    return (np.array(a).view('u1')-48).reshape(len(a),-1)
样本运行-

In [143]: listOfStringOfINTs = ["123231231231231"]*5

In [144]: get_int_ar(listOfStringOfINTs)
Out[144]: 
array([[1, 2, 3, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1],
       [1, 2, 3, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1],
       [1, 2, 3, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1],
       [1, 2, 3, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1],
       [1, 2, 3, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1]], dtype=uint8)

下面是一个使用
”的解决方案。加入

def digit_ize(a):
    r = np.fromstring(''.join(a), 'u1')
    r &= 0x0f
    return r.reshape(len(a), -1)
或者(稍微快一点):

时间:

small
pp1 4.314555088058114
pp2 2.933372976258397
div 3.740947926416993
usr 29.473979957401752
hpj 12.974489014595747
large
pp1 9.718517074361444
pp2 7.069707033224404
div 37.66830707900226
usr 2321.8201039126143
hpj 1103.1720889732242
用于生成计时的脚本,在必要时包含其他Soln的Py3调整

import numpy as np

def digit_ize():
    r = np.fromstring(''.join(a), 'u1')
    r &= 0x0f
    return r.reshape(len(a), -1)

def digit_ize_2():
    r = np.frombuffer(''.join(a).encode(), 'u1') & 0x0f
    return r.reshape(len(a), -1)

def get_int_ar():
    return (np.array(a, 'S').view('u1')-48).reshape(len(a),-1)

def use_vstack():
    np.vstack(np.frombuffer(b.encode(), dtype=np.uint8)-48 for b in a)

def use_list():
    return np.array([list(astr) for astr in a],int)           

from timeit import timeit

listOfStringOfINTs = ["123231231231231"]*5
a = listOfStringOfINTs
print("small")
print("pp1", timeit(digit_ize, number=1000)*1000)
print("pp2", timeit(digit_ize_2, number=1000)*1000)
print("div", timeit(get_int_ar, number=1000)*1000)
print("usr", timeit(use_vstack, number=1000)*1000)
print("hpj", timeit(use_list, number=1000)*1000)
a = a*100
print("large")
print("pp1", timeit(digit_ize, number=1000)*1000)
print("pp2", timeit(digit_ize_2, number=1000)*1000)
print("div", timeit(get_int_ar, number=1000)*1000)
print("usr", timeit(use_vstack, number=1000)*1000)
print("hpj", timeit(use_list, number=1000)*1000)

在Python中,变量名的驼峰大小写不是一个好的实践。使用“snake_case”代替。感谢您的提示,我们将在将来尝试使用它。每个字符串中的字符数是否相同?Camel case不是“坏”做法。Snake-case只是Python中的首选约定。我更喜欢camel,所以我使用camel,并且在读取函数和变量名时没有问题。@Divakar是的,所有函数和变量都有相同数量的字符。我从一个二进制文件中获取它们(最佳情况下,我会将不同于int列表的字符串保存并加载到二进制文件中,但这就是我在时间限制内所能想到的)
import numpy as np

def digit_ize():
    r = np.fromstring(''.join(a), 'u1')
    r &= 0x0f
    return r.reshape(len(a), -1)

def digit_ize_2():
    r = np.frombuffer(''.join(a).encode(), 'u1') & 0x0f
    return r.reshape(len(a), -1)

def get_int_ar():
    return (np.array(a, 'S').view('u1')-48).reshape(len(a),-1)

def use_vstack():
    np.vstack(np.frombuffer(b.encode(), dtype=np.uint8)-48 for b in a)

def use_list():
    return np.array([list(astr) for astr in a],int)           

from timeit import timeit

listOfStringOfINTs = ["123231231231231"]*5
a = listOfStringOfINTs
print("small")
print("pp1", timeit(digit_ize, number=1000)*1000)
print("pp2", timeit(digit_ize_2, number=1000)*1000)
print("div", timeit(get_int_ar, number=1000)*1000)
print("usr", timeit(use_vstack, number=1000)*1000)
print("hpj", timeit(use_list, number=1000)*1000)
a = a*100
print("large")
print("pp1", timeit(digit_ize, number=1000)*1000)
print("pp2", timeit(digit_ize_2, number=1000)*1000)
print("div", timeit(get_int_ar, number=1000)*1000)
print("usr", timeit(use_vstack, number=1000)*1000)
print("hpj", timeit(use_list, number=1000)*1000)