2015-08-15 4 views
4

Я пытаюсь обрабатывать данные, хранящиеся в текстовом файле, который выглядит как этот test.dat:Как читать только определенные строки из текстового файла?

-1411.85 2.6888 -2.09945 -0.495947 0.835799 0.215353 0.695579 
-1411.72 2.82683 -0.135555 0.928033 -0.196493 -0.183131 -0.865999 
-1412.53 0.379297 -1.00048 -0.654541 -0.0906588 0.401206 0.44239 
-1409.59 -0.0794765 -2.68794 -0.84847 0.931357 -0.31156 0.552622 
-1401.63 -0.0235102 -1.05206 0.065747 -0.106863 -0.177157 -0.549252 
.... 
.... 

файл, однако, несколько Гб, и я бы очень хотел, чтобы прочитать его, в небольших блоках строк. Я хотел бы использовать функцию numpy'sloadtxt, так как это быстро преобразует все в numpy array. Тем не менее, я не был в состоянии управлять до сих пор, как функция, кажется, только предлагают выбор столбцов, как здесь:

data = np.loadtxt("test.dat", delimiter=' ', skiprows=1, usecols=range(1,7)) 

Любые идеи, как этого добиться? Если невозможно с loadtxt любые другие варианты, доступные в Python?

+0

loadtxt аргумент fname может быть генератором, поэтому для чтения небольших блоков строк используется генератор чтения файла, такой как показано в ответе nosklo в http://stackoverflow.com/questions/519633/lazy-method-for-reading-big -file-in-python, но преобразуется для чтения только небольшого количества строк вместо байтов. –

+1

См. Также: http://stackoverflow.com/a/27962976/901925 - 'Самый быстрый способ читать каждую n-ю строку с genfromtxt numpy' – hpaulj

ответ

1

hpaulj указал мне в правильном направлении в своем комментарии.

Используя следующий код отлично работает для меня:

import numpy as np 
import itertools 
with open('test.dat') as f_in: 
    x = np.genfromtxt(itertools.islice(f_in, 1, 12, None), dtype=float) 
    print x[0,:] 

Спасибо большое!

2

Если вы можете использовать pandas, что было бы проще:

In [2]: import pandas as pd 

In [3]: df = pd.read_table('test.dat', delimiter=' ', skiprows=1, usecols=range(1,7), nrows=3, header=None) 

In [4]: df.values 
Out[4]: 
array([[ 2.82683 , -0.135555 , 0.928033 , -0.196493 , -0.183131 , 
     -0.865999 ], 
     [ 0.379297 , -1.00048 , -0.654541 , -0.0906588, 0.401206 , 
     0.44239 ], 
     [-0.0794765, -2.68794 , -0.84847 , 0.931357 , -0.31156 , 
     0.552622 ]]) 

Редактировать

Если вы хотите прочитать сказать каждые k строк, вы можете указать chunksize. Например,

reader = pd.read_table('test.dat', delimiter=' ', usecols=range(1,7), header=None, chunksize=2) 
for chunk in reader: 
    print(chunk.values) 

Out:

[[ 2.6888 -2.09945 -0.495947 0.835799 0.215353 0.695579] 
[ 2.82683 -0.135555 0.928033 -0.196493 -0.183131 -0.865999]] 
[[ 0.379297 -1.00048 -0.654541 -0.0906588 0.401206 0.44239 ] 
[-0.0794765 -2.68794 -0.84847 0.931357 -0.31156 0.552622 ]] 
[[-0.0235102 -1.05206 0.065747 -0.106863 -0.177157 -0.549252 ]] 

Вы должны обращаться, как хранить их в течение петли, как вы хотите. Обратите внимание, что в этом случае reader - это TextFileReader, а не DataFrame, поэтому вы можете проходить через него лениво.

Для получения более подробной информации вы можете прочитать this.

+0

Я не вижу, как бы я, например, прочитал первые три, а затем второй три и т. д. Не могли бы вы объяснить это, пожалуйста? Спасибо за ваши старания! –

+0

Вы имеете в виду прочесть первые три в ndarray, затем следующие три в другой ndarray и так далее? – yangjie

+0

Да, это то, что мне нужно! –

1

Возможно, вы захотите использовать рецепт itertools.

from itertools import izip_longest 
import numpy as np 


def grouper(n, iterable, fillvalue=None): 
    args = [iter(iterable)] * n 
    return izip_longest(fillvalue=fillvalue, *args) 


def lazy_reader(fp, nlines, sep, skiprows, usecols): 
    with open(fp) as inp: 
     for chunk in grouper(nlines, inp, ""): 
      yield np.loadtxt(chunk, delimiter=sep, skiprows=skiprows, usecols=usecols) 

Функция возвращает генератор массивов.

lazy_data = lazy_reader(...) 
next(lazy_data) # this will give you the next chunk 
# or you can iterate 
for chunk in lazy_data: 
    ... 
Смежные вопросы