2015-12-08 3 views
1

У меня есть большой текстовый файл в формате svmlight. Он содержит строки пространства, разделенные парами индексов (int) и значения (float), разделенные точкой с запятой.Быстрое чтение файла svmlight кусками

Пример:

1:2 4:12 5:3 ... 
2:34 4:2 12:5 ... 

Файл может быть очень большим, и это не представляется возможным прочитать его весь сразу в Numpy массиве.

Как лучше всего прочитать такой файл кусками? Или, может быть, более правильный вопрос заключается в том, как эффективно создать массив numpy в такой ситуации?

На данный момент я использую следующий код. lines - это список строк, считанных из файла.

x = [] 
    for line in lines: 
     tmp = re.split('[ :]', line) 
     out = [0] * len(self.__varnames) 
     for i in range(0, len(tmp), 2): 
      out[int(tmp[i])] = float(tmp[i+1]) 
     x.append(out) 
    x = np.asarray(x) 

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

ПРИМЕЧАНИЕ:

1) load_svmlight_file из пакета sklearn считывает файл в целом, и он не может прочитать файл без ведущего класса ярлыка, который является необязательным.

2) Я ожидаю найти быстрое решение без зависимостей от внешних библиотек (если таковые существуют). Но, конечно, допускаются numpy, scipy.

ответ

0

Вы можете получить строки чтения в кусках.

Здесь представлено простое решение для обоих случаев.

def yield_file(infile): 
    '''(file_path) >> line 
    A simple generator that yields the lines of a file. 
    ''' 

    with open(infile, 'r') as f: 
     for line in f: 
      yield line 


def read_in_chunks(infile, chunk_size=1024): 
    '''(file_path, int) >> str 
    Simple generator to read a file in chunks. 
    ''' 

    with open(infile,'r') as f: 
     while True: 
      data = f.read(chunk_size) 
      if not data: 
       break 
      yield data 
+0

Спасибо, но это не решит проблему скорости. Ограничение скорости - это создание массива. Я упомянул «прочитать файл кусками», чтобы избежать советов по использованию функций из известных пакетов. – DrDom

0

Вы можете получить немного чище и не нуждаются в регулярном выражении:

x = [] 
for line in lines: 
    out = [0] * len(self.__varnames) 
    for entry in line.split(): 
     index, value = entry.split(':') 
     out[int(index)] = float(value) 
    x.append(out) 
x = np.array(x) 

Понятия не имею, если это быстрее. Необходимо протестировать.

+0

Спасибо. Скорость почти такая же. Возможно, для очень длинных строк будет какая-то разница. – DrDom

+0

Возможно ограничение скорости жесткого диска. Сравните с пустым циклом .: 'для строки в строках: pass' для вашего большого файла. –