Вопрос по numpy, block, python – Чтение блоков данных из файла в Python

5

Я новичок в Python и пытаюсь прочитать "блоки" данных из файла. Файл написан примерно так:

<code># Some comment
# 4 cols of data --x,vx,vy,vz
# nsp, nskip =           2          10


#            0   0.0000000


#            1           4
 0.5056E+03  0.8687E-03 -0.1202E-02  0.4652E-02
 0.3776E+03  0.8687E-03  0.1975E-04  0.9741E-03
 0.2496E+03  0.8687E-03  0.7894E-04  0.8334E-03
 0.1216E+03  0.8687E-03  0.1439E-03  0.6816E-03


#            2           4
 0.5056E+03  0.8687E-03 -0.1202E-02  0.4652E-02
 0.3776E+03  0.8687E-03  0.1975E-04  0.9741E-03
 0.2496E+03  0.8687E-03  0.7894E-04  0.8334E-03
 0.1216E+03  0.8687E-03  0.1439E-03  0.6816E-03


#          500  0.99999422


#            1           4
 0.5057E+03  0.7392E-03 -0.6891E-03  0.4700E-02
 0.3777E+03  0.9129E-03  0.2653E-04  0.9641E-03
 0.2497E+03  0.9131E-03  0.7970E-04  0.8173E-03
 0.1217E+03  0.9131E-03  0.1378E-03  0.6586E-03

and so on
</code>

Теперь я хочу иметь возможность указать и прочитать только один блок данных из этих многих блоков. Я используюnumpy.loadtxt('filename',comments='#') читать данные, но загружает весь файл за один раз. Я искал в Интернете, и кто-то создал патч для подпрограммы numpy io, чтобы указать блоки чтения, но он не входит в основной поток numpy.

Намного проще выбирать блоки данных в gnuplot, но мне нужно написать подпрограмму для построения функций распределения. Если бы я смог разобраться с чтением определенных блоков, в Python было бы намного проще. Кроме того, я перемещаю все свои коды визуализации в python из IDL и gnuplot, поэтому было бы неплохо иметь все в python вместо того, чтобы разбрасывать их по нескольким пакетам.

Я думал о вызове gnuplot из Python, построении блока для таблицы и назначении вывода некоторому массиву в Python. Но я все еще начинаю и не могу понять синтаксис, чтобы сделать это.

Любые идеи, указатели для решения этой проблемы будут очень полезны.

Alsmot! Точная вещь, которую я хочу уметь - это указывать i, j, где i - начальный блок, а j - последний блок, а блок определяется строками, разделенными двумя или более пустыми строками. toylas
Таким образом, вы хотите, чтобы пользователь указал, скажем, пару значений (i, j) и прочитал все строки между строкой "# i j" а следующая пустая строка? Pascal Bugnion

Ваш Ответ

2   ответа
0

Следующий код, вероятно, поможет вам начать. Вам, вероятно, понадобится модуль re.

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

f = open("file_name_here")

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

line = f.readline()

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

while not line.startswith("#"):
    line = f.readline()

Чтобы проанализировать строку, которая выглядит как & quot; # i j & quot ;, вы можете использовать следующее регулярное выражение:

is_match = re.match("#\s+(\d+)\s+(\d+)",line)
if is_match:
    i = is_match.group(1)
    j = is_match.group(2)

См. Документацию для & quot; re & quot; Модуль для получения дополнительной информации об этом.

Для разбора блока вы можете использовать следующий бит кода:

block = [[]] # block[i][j] will contain element i,j in your block
while not line.isspace(): # read until next blank line
    block.append(map(float,line.split(" "))) 
    # splits each line at each space and turns all elements to float
    line = f.readline()

Затем вы можете превратить ваш блок в пустой массив, если хотите:

block = np.array(block)

При условии, что вы импортировали numpy как np. Если вы хотите прочитать несколько блоков между i и j, просто поместите приведенный выше код, чтобы прочитать один блок в функцию и использовать его несколько раз.

Надеюсь это поможет!

Большое спасибо, Паскаль! Я решил отделить строку от вашего поста и использовал ее в предложении Эммануала. В конечном итоге я осуществлю ваше предложение по синтаксическому анализу текста из "#". линии тоже, но сейчас, я просто должен получить рабочий код и сделать несколько графиков в течение этой недели! Вздох... toylas
5

Краткое прочтение:

>>> def read_blocks(input_file, i, j):
    empty_lines = 0
    blocks = []
    for line in open(input_file):
        # Check for empty/commented lines
        if not line or line.startswith('#'):
            # If 1st one: new block
            if empty_lines == 0:
                blocks.append([])
            empty_lines += 1
        # Non empty line: add line in current(last) block
        else:
            empty_lines = 0
            blocks[-1].append(line)
    return blocks[i:j + 1]

>>> for block in read_blocks(s, 1, 2):
    print '-> block'
    for line in block:
        print line


-> block
 0.5056E+03  0.8687E-03 -0.1202E-02  0.4652E-02
 0.3776E+03  0.8687E-03  0.1975E-04  0.9741E-03
 0.2496E+03  0.8687E-03  0.7894E-04  0.8334E-03
 0.1216E+03  0.8687E-03  0.1439E-03  0.6816E-03
-> block
 0.5057E+03  0.7392E-03 -0.6891E-03  0.4700E-02
 0.3777E+03  0.9129E-03  0.2653E-04  0.9641E-03
 0.2497E+03  0.9131E-03  0.7970E-04  0.8173E-03
 0.1217E+03  0.9131E-03  0.1378E-03  0.6586E-03
>>> 

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

Спасибо! Кажется, это намного чище, чем я. toylas
Спасибо за подтверждение! Что касается вашего вопроса, я не понимаю, почемуb=np.array(a.split()).astype(float) не будет работать.
Есть ли более элегантный способ реализации в этой линии? б = a.split (); б = np.array (б); б = b.astype (с плавающей точкой) toylas
Большое спасибо, Эммануэль! Это работало почти точно из коробки. Мне нужно было выучить несколько битов и позаботиться о пробелах в моих файлах и т. Д. Я также реализовал предложение Паскаля разделить строку перед добавлением блока. Теперь окончательный код дает мне трехмерный массив с каждым блоком как плоскость в трехмерном массиве. Большое спасибо за помощь! Я хотел бы выучить Python немного быстрее. toylas

Похожие вопросы