Преобразование списка строк в массиве Numpy более быстрым способом - PullRequest
7 голосов
/ 31 августа 2011

br - это имя списка строк, которое выглядит следующим образом:

['14 0.000000 -- (long term 0.000000)\n',
 '19 0.000000 -- (long term 0.000000)\n',
 '22 0.000000 -- (long term 0.000000)\n',
...

Меня интересуют первые два столбца, которые я хотел бы преобразовать в массив numpy. Пока что я нашел следующее решение:

x = N.array ([0., 0.])
for i in br:
    x = N.vstack ( (x, N.array (map (float, i.split ()[:2]))) )

В результате получается двумерный массив:

array([[  0.,   0.],
       [ 14.,   0.],
       [ 19.,   0.],
       [ 22.,   0.],
...

Однако, поскольку br довольно большой (~ 10 ^ 5 записей), эта процедура занимает некоторое время. Мне было интересно, есть ли способ достичь того же результата, но за меньшее время?

Ответы [ 3 ]

4 голосов
/ 31 августа 2011

Это значительно быстрее для меня:

import numpy as N

br = ['14 0.000000 -- (long term 0.000000)\n']*50000
aa = N.zeros((len(br), 2))

for i,line in enumerate(br):
    al, strs = aa[i], line.split(None, 2)[:2]
    al[0], al[1] = float(strs[0]), float(strs[1])

Изменения:

  • Предварительно выделить массив NumPy (это большой). Вы уже знаете, что вам нужен двумерный массив с определенными размерами.
  • Только split () для первых 2 столбцов, поскольку остальные вам не нужны.
  • Не используйте map (): это медленнее, чем списки. Я даже не использовал списочные выражения, поскольку вы знаете, что у вас есть только 2 столбца.
  • Назначение непосредственно в предварительно выделенный массив вместо генерации новых временных массивов во время итерации.
2 голосов
/ 31 августа 2011

Вы можете попытаться предварительно обработать (с помощью awk для примера) список строк, если они происходят из файла, и использовать numpy.fromtxt. Если вы не можете ничего сделать с тем, как вы получили этот список, у вас есть несколько возможностей:

  • сдавайся. Вы будете запускать эту функцию один раз в день. Вам не важна скорость, и ваше реальное решение достаточно хорошее
  • написать плагин ввода-вывода с Cython. У вас большой потенциальный выигрыш, потому что вы сможете делать все циклы в c, и напрямую влияет на значения в большом (10 ^ 5, 2) numpy ndarray
  • попробуйте другой язык, чтобы решить вашу проблему. Если вы используете такие языки, как c или haskell, вы можете использовать ctypes для вызова функций, скомпилированных в dll из python

1012 * редактировать *

может быть, этот подход немного быстрее:

def conv(mysrt):
    return map(float, mystr.split()[:2])

br_float = map(conv, br)
x = N.array(br_float)
1 голос
/ 31 августа 2011

Изменение

map (float, i.split()[:2])

на

map (float, i.split(' ',2)[:2])

может привести к небольшому ускорению.Поскольку вы заботитесь только о первых двух разделенных пробелами элементах в каждой строке, нет необходимости разбивать всю строку.2 в i.split(' ',2) указывает split сделать максимум 2 разделения.Например,

In [11]: x='14 0.000000 -- (long term 0.000000)\n' 

In [12]: x.split()
Out[12]: ['14', '0.000000', '--', '(long', 'term', '0.000000)']

In [13]: x.split(' ',2)
Out[13]: ['14', '0.000000', '-- (long term 0.000000)\n']
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...