Есть ли более эффективный способ преобразования нескольких строк строки в массив Numpy? - PullRequest
3 голосов
/ 30 апреля 2019

Я преобразую несколько строк строки в массив 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 ]

4 голосов
/ 02 мая 2019

Один ответ был помечен как некачественный из-за отсутствия объяснений.Но ни один из остальных трех не делает этого, и они просто реплики друг друга.

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']
3 голосов
/ 30 апреля 2019
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 голосов
/ 30 апреля 2019

Вы можете использовать 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]]
1 голос
/ 30 апреля 2019
from io import StringIO
np.genfromtxt(StringIO(names), dtype=np.int)
0 голосов
/ 30 апреля 2019

Вы можете использовать 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]]
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...