ускоренная функция Python для обработки файлов с сегментами данных, разделенными пробелом - PullRequest
2 голосов
/ 22 февраля 2010

Мне нужно обработать файлы с сегментами данных, разделенными пробелом, например:

93.18 15.21 36.69 33.85 16.41 16.81 29.17 
21.69 23.71 26.38 63.70 66.69 0.89 39.91 
86.55 56.34 57.80 98.38 0.24 17.19 75.46 
[...]
1.30 73.02 56.79 39.28 96.39 18.77 55.03

99.95 28.88 90.90 26.70 62.37 86.58 65.05 
25.16 32.61 17.47 4.23 34.82 26.63 57.24 
36.72 83.30 97.29 73.31 31.79 80.03 25.71 
[...]
2.74 75.92 40.19 54.57 87.41 75.59 22.79

.
.
.

для этого я использую следующую функцию. При каждом вызове я получаю необходимые данные, но мне нужно ускорить код.

Есть ли более эффективный способ?

РЕДАКТИРОВАТЬ : Я буду обновлять код с изменениями, которые улучшают

ОРИГИНАЛ:

def get_pos_nextvalues(pos_file, indices):
    result = []
    for line in pos_file:
        line = line.strip()
        if not line:
            break
        values = [float(value) for value in line.split()]
        result.append([float(values[i]) for i in indices])
    return np.array(result)

NEW

def get_pos_nextvalues(pos_file, indices):
    result = ''
    for line in pos_file:
        if len(line) > 1:
            s = line.split()
            result += ' '.join([s [i] for i in indices])
        else:
            break
    else:
        return np.array([])
    result = np.fromstring(result, dtype=float, sep=' ')
    result = result.reshape(result.size/len(indices), len(indices))
    return result

.

pos_file = open(filename, 'r', buffering=1024*10)

[...]

while(some_condition):
    vs = get_pos_nextvalues(pos_file, (4,5,6))
    [...]

ускорение = 2,36

Ответы [ 6 ]

2 голосов
/ 22 февраля 2010

не конвертировать поплавки в поплавки будет первым шагом. Однако я бы предложил сначала профилировать ваш код , а затем попытаться оптимизировать узкие места.

Я понимаю, что вы изменили свой код с исходного, но

values = [value for value in line.split()]

тоже не очень хорошая вещь. просто напишите values = line.split(), если вы это имеете в виду.

Видя, как вы используете NumPy, я бы предложил методы чтения файлов, которые продемонстрированы в их документах .

1 голос
/ 23 февраля 2010

Вместо:

if len(line) <= 1: # only '\n' in «empty» lines
    break
values = line.split()

попробуйте это:

values = line.split()
if not values: # line is wholly whitespace, end of segment
    break
1 голос
/ 22 февраля 2010

попробуйте увеличить буфер чтения, IO, вероятно, является узким местом вашего кода

open('file.txt', 'r', 1024 * 10) 

также, если данные полностью последовательны, вы можете попытаться пропустить построчный код и преобразовать сразу несколько строк

1 голос
/ 22 февраля 2010

Вы читаете каждый символ ровно один раз, так что никакой реальной производительности вы не получите.

Вы можете комбинировать strip и split, если пустые строки содержат много пробелов.

Вы также можете сэкономить некоторое время, инициализируя массив numpy с самого начала, вместо того, чтобы сначала создавать массив python, а затем преобразовывать.

0 голосов
/ 23 февраля 2010

Вот вариант, что может быть быстрее для нескольких индексов. Он строит строку только из желаемых значений, поэтому np.fromstring выполняет меньше работы.

def get_pos_nextvalues_fewindices(pos_file, indices):
    result = ''
    for line in pos_file:
        if len(line) > 1:
            s = line.split()
            for i in indices:
                result += s[i] + ' '
        else:
            return np.array([])
    result = np.fromstring(result, dtype=float, sep=' ')
    result = result.reshape(result.size/len(indeces), len(indeces))
    return result

Это меняет накладные расходы на split() и добавляет цикл для меньшего разбора. Или, может быть, есть какой-то хитрый трюк с регулярными выражениями, который вы можете сделать, чтобы извлечь нужные подстроки напрямую?

Старый ответ

np.mat('1.23 2.34 3.45 6\n1.32 2.43 7 3.54') преобразует строку в numpy матрицу значений с плавающей запятой. Это может быть более быстрое ядро ​​для вас. Например:

import numpy as np
def ReadFileChunk(pos_file):
    chunktxt = ""
    for line in pos_file:
        if len(line) > 1:
            chunktxt = chunktxt + line
        else:
            break

    return np.mat(chunktxt).tolist()
    # or alternatively
    #return np.array(np.mat(s))

Затем вы можете переместить ваши элементы индексации в другую функцию. Надеемся, что numpy внутренний анализ строки быстрее, чем повторный вызов float().

0 голосов
/ 22 февраля 2010

numpy.fromfile у вас не работает?

arr = fromfile('tmp.txt', sep=' ', dtype=int)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...