有没有更有效的方法将多行字符串转换为numpy数组?

时间:2019-04-30 09:10:27

标签: python numpy

我正在将多行字符串转换为numpy数组,如下所示:

names = """
1 2 1
1 1 0
0 1 1
"""
names_list = names.splitlines()
tem = []
for i in [row for row in names_list if row]:
    tem.append([col for col in list(i) if col != ' '])

np.array(tem, dtype=np.int)

虽然这段代码有效,但我想知道是否有更有效的方法来做到这一点?

5 个答案:

答案 0 :(得分:4)

一个回答被标记为质量低,原因是不解释自己。但是其他三个都没有这样做,它们只是彼此的复制品。

In [227]: names = """ 
     ...: 1 2 1 
     ...: 1 1 0 
     ...: 0 1 1 
     ...: """    

In [238]: np.genfromtxt(StringIO(names), dtype=int)                                  
Out[238]: 
array([[1, 2, 1],
       [1, 1, 0],
       [0, 1, 1]])
In [239]: timeit np.genfromtxt(StringIO(names), dtype=int)                           
135 µs ± 286 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)

实际上,我们不需要StringIO层;只需将字符串分成几行(有时我们需要一个format=None参数):

In [242]: np.genfromtxt(names.splitlines(), dtype=int)                               
Out[242]: 
array([[1, 2, 1],
       [1, 1, 0],
       [0, 1, 1]])

原始功能比接受的功能快10倍:

def orig(names):
    names_list = names.splitlines()
    tem = []
    for i in [row for row in names_list if row]:
        tem.append([col for col in list(i) if col != ' '])
    return np.array(tem, dtype=np.int)

In [244]: orig(names)                                                                
Out[244]: 
array([[1, 2, 1],
       [1, 1, 0],
       [0, 1, 1]])
In [245]: timeit orig(names)                                                         
11.1 µs ± 194 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)

genfromtxt基本上执行相同的操作-分割线,在列表列表中收集值,然后将其转换为数组。它尚未编译。

标记的答案用split方法代替列表理解:

def czisws(names):
    names_list = names.splitlines()
    tem = []
    for i in [row for row in names_list if row]:
        tem.append(i.split())
    return np.array(tem, dtype=np.int)

In [247]: timeit czisws(names)                                                       
8.58 µs ± 274 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)

速度更快,这不足为奇。 split是一个字符串方法。内置方法通常更快,即使不是,也更可取。

拆分也更通用:

In [251]: 'abc de f'.split()                                                         
Out[251]: ['abc', 'de', 'f']
In [252]: [i for i in list('abc de f') if i!=' ']                                    
Out[252]: ['a', 'b', 'c', 'd', 'e', 'f']

答案 1 :(得分:3)

names = """
1 2 1
1 1 0
0 1 1
"""
names_list = names.splitlines()
tem = []
for i in [row for row in names_list if row]:
    tem.append(i.split(" "))

np.array(tem, dtype=np.int)

答案 2 :(得分:2)

您可以使用np.genfromtxt

例如:

import numpy as np
from io import BytesIO

names = """
1 2 1
1 1 0
0 1 1
"""
print(np.genfromtxt(BytesIO(names), dtype=np.int)) #Python3 use BytesIO(names.encode('utf-8'))

输出:

[[1 2 1]
 [1 1 0]
 [0 1 1]]

答案 3 :(得分:1)

from io import StringIO
np.genfromtxt(StringIO(names), dtype=np.int)

答案 4 :(得分:0)

对于np.genfromtxt,您可以按以下方式使用Python 3

import numpy as np
from io import BytesIO

names = """
1 2 1
1 1 0
0 1 1
"""
print(np.genfromtxt(BytesIO(names.encode('utf-8')), dtype=np.int))
#print(np.genfromtxt(BytesIO(names), dtype=np.int)) for Python 2

您将得到的输出为

[[1 2 1]
 [1 1 0]
 [0 1 1]]