Как извлечь данные из файла данных неправильного формата в Python

Мне нужно извлечь определенные данные из файла, но этот файл отформатирован для чтения людьми, и поэтому является нерегулярным. Прежде всего, перед тем, как начнутся какие-либо данные, появляется большой объем текста:

   DL_POLY Version 2.20

                        Running on   10 nodes



*************** ДЛПОЛИЯ: LiNbO3 >***************




ПАРАМЕТРЫ УПРАВЛЕНИЯ МОДЕЛИРОВАНИЕМ

температура моделирования 1.4500E + 03

моделирование давления (катм) 0.0000E+00

выбранное количество шагов 8000

период уравновешивания 500

интервал печати данных 80

интервал файла статистики 80

время моделирования 5.0000E-04

Нос-Гувер (Melchionna) изотропный NPT термостат время релаксации 1.0000E-01 время релаксации баростата 5.0000E-01

опция файла траектории на
начало файла траектории 1 интервал файла траектории 80 ключ информации о файле траектории 2...

Затем через некоторое время появляются фактические данные, но они находятся в такой забавной форме:


step_tot temp_tot eng_cfg eng_vdw eng_cou eng_bnd > eng_ang eng_dih eng_tet time(ps) eng_pv temp_rot vir_cfg vir_vdw vir_cou vir_bnd >vir_ang vir_con vir_tet ЦП (s) тома temp_shl eng_fam_maflma_flf_flma_flf_f_f_fl_f_f_f_l_f_f_f_f_l_f_l_f_f_l_t_p_l_


1 -1.1289E + 05 1.4750E + 03 -1.1386E + 05 1.7276E + 04 -1.3114E + 05 0,0000E + 00> 0,0000E + 00 0,0000E + 00 0,0000E + 00 0,0 -1,1545E + 05 0,0000E + 00 9.6539E + 03 -1.2118E + 05 1.3083E + 05 0.0000E + 00> 0.0000E + 00 0.0000E + 00 0.0000E + 00 0.8 5.3733E + 04 1.2367E + 02 0.0000E + 00 0.0000E + 00 5.6396E +01 5,6396E + 01> 5,6396E + 01 0,0000E + 00 -7,5549E + 01

прокатка -1.1289E + 05 1.4750E + 03 -1.1386E + 05 1.7276E + 04 -1.3114E + 05 0.0000E + 00> 0.0000E + 00 0.0000E + 00 0.0000E + 00 в среднем -1.1545E + 05 0.0000E + 00 9,6539E + 03 -1,2118E + 05 1,3083E + 05 0,0000E + 00> 0,0000E + 00 0,0000E + 00 0,0000E + 00 5,3733E + 04 1,2367E + 02 0,0000E + 00 0,0000E + 00 5,6396E + 01 5.6396E + 01> 5.6396E + 01 0.0000E + 00 -7.5549E + 01


80 -1.1290E + 05 1.5021E + 03 -1.1392E + 05 2.1894E + 04 -1.3726E + 05 0,0000E + 00> 0,0000E + 00 0,0000E + 00 0,0000E + 00 0,0 -1,1256E + 05 0,0000E + 00 8,6671E + 02 -1,3974E + 05 1,3707E + 05 0,0000E + 00> 0,0000E + 00 0,0000E + 00 0,0000E + 00 10,6 5,3149E + 04 1,1377E + 03 1,4419E + 03 3,5382E + 03 5,6396E +01 5,6396E + 01> 5,6396E + 01 0,0000E + 00 1,1119E + 01

прокатка -1.1290E + 05 1.6145E + 03 -1.1398E + 05 2.0750E + 04 -1.3588E + 05 0.0000E + 00> 0.0000E + 00 0.0000E + 00 0.0000E + 00 в среднем -1.1333E + 05 0.0000E + 00 3.3694E + 03 -1.3512E + 05 1.3565E + 05 0.0000E + 00> 0.0000E + 00 0.0000E + 00 0.0000E + 00 5.3481E + 04 1.0997E + 03 1.1430E + 03 2.8391E + 03 5.6396E + 01 5.6396E + 01> 5.6396E + 01 0.0000E + 00 -1.2096E + 01


160 -1,1287E + 05 1,2629E + 03 -1,1376E + 05 2,1450E + 04 -1,3633E + 05 0,0000E + 00> 0,0000E + 00 0,0000E + 00 0,0000E + 00 0,1 -1,1249E + 05 0,0000E + 00 3.8761E + 02 -1.3824E + 05 1.3612E + 05 0.0000E + 00> 0.0000E + 00 0.0000E + 00 0.0000E + 00 20.5 5.3375E + 04 4.9015E + 02 1.1243E + 03 2.5052E + 03 5.6396E +01 5,6396E + 01> 5,6396E + 01 0,0000E + 00 1,2676E + 01

прокатка -1.1288E + 05 1.4677E + 03 -1.1389E + 05 2.1589E + 04 -1.3663E + 05 0.0000E + 00 0.0000E + 00 0.0000E + 00 0.0000E + 00 в среднем -1.1235E + 05 0.0000E + 00 2.1147E + 02 -1.3884E + 05 1.3643E + 05 0.0000E + 00> 0.0000E + 00 0.0000E + 00 0.0000E + 00 5.3152E + 04 7.4818E + 02 1.1440E + 03 2.6211E + 03 5.6396E + 01 5,6396E + 01> 5,6396E + 01 0,0000E + 00 1,7174E + 01


На 9-м интервале данных наблюдается небольшая анамолия:


отключение температурного масштабирования на шаге 500


 560 -1.1287E+05  1.4709E+03 -1.1390E+05  2.1600E+04 -1.3678E+05  0.0000E+00  >0.0000E+00  0.0000E+00  0.0000E+00
 0.3 -1.1292E+05  0.0000E+00  1.9253E+03 -1.3743E+05  1.3656E+05  0.0000E+00  >0.0000E+00  0.0000E+00  0.0000E+00
68.4  5.4300E+04  1.5043E+02  1.2775E+03  2.7947E+03  5.6396E+01  5.6396E+01  >5.6396E+01  0.0000E+00  2.0576E-01

прокатка -1.1286E + 05 1.4784E + 03 -1.1390E + 05 2.1546E + 04 -1.3673E + 05 0,0000E + 00> 0,0000E + 00 0,0000E + 00 0,0000E + 00 в среднем -1.1298E + 05 0,0000E + 00 2.1361E + 03 -1.3717E + 05 1.3651E + 05 0.0000E + 00> 0.0000E + 00 0.0000E + 00 0.0000E + 00 5.4303E + 04 2.2261E + 02 1.2785E + 03 2.8027E + 03 5.6396E + 01 5.6396E + 01> 5.6396E + 01 0.0000E + 00 -1.7421E + 00



Как вы можете видеть, есть пара строк "----", которые могут помешать правильному анализу данных.

Допустим, я хочу получить из этого файла только данные "eng_tot" (цифры, выделенные полужирным шрифтом), как мне поступить в Python? Число всегда находится в одном и том же месте в файле (вторая величина, первая строка после второго набора ---- s.

Кстати, часть заголовка со всеми определениями в ней повторяется каждые 8 ​​шагов, кроме первого шага, в котором есть 9 строк. Я хотел бы просто проигнорировать первый шаг. А пока, допустим, я хочу начать со строки 295 включительно. Как вы знаете, я довольно плохо знаком с Python и программированием в целом, поэтому вся помощь, которую вы можете предоставить, ценится.

Вот код, который я пробовал, но Eng_Total по-прежнему пустой набор:

import re
import inspect

def lineno():
    """Returns the current line number"""
    linenum = inspect.currentframe().f_back.f_lineno
infile =  open('FilePath/OUTPUT.01').read()
Eng_Total = []
for line in infile:
#    if 'eng_tot' in line.split(): 
     if re.match("\s+-+\s+", line):
    lineno(line)
        line = linenum+1
        sanitized_line = line[8:]
        eng_total = line.split()[0]
        Eng_Total.append(eng_total)
print Eng_Total

2 ответа

Решение

Я бы, наверное, сделал это:

  • перебирать строки в выводе
  • поиск, содержащий eng_tot:
    • if 'eng_tot' in line.split(): process_blocks
  • сожрать строки, пока один не совпадет со всеми тире (с необязательными пробелами с обеих сторон)
    • if re.match("\s+-+\s+", line): proccess_metrics_block
  • обработать первую строку метрик:
    • вырежьте первый столбец из строки (это затруднит анализ, потому что его там может не быть)
      • sanitized_line = line[8:]
      • eng_total = line.split()[0] первый столбец теперь eng_total
  • пропускайте строки, пока не достигнете другой линии тире, затем начните снова

После просмотра ваших правок:

  • Вам необходимо импортировать re (регулярное выражение) модуль, вверху файла: import re
  • process_blocks а также process_metrics_block были псевдокод. Они не существуют, если вы не определите их.:) Точно не нужны эти функции, вы можете избежать их, используя базовые циклы (while) и условно (if) заявления.
  • Вы должны убедиться, что понимаете, что делаете, а не просто копировать из переполнения стека!:)

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

import re

def find_header(lines):
  for (i, line) in enumerate(lines):
    if 'eng_tot' in line.split():
      return i
  return None

def find_next_separator(lines, start):
  for (i, line) in enumerate(lines[start+1:]):
    if re.match("\s*-+\s*", line):
      return i + start + 1
  return None

if __name__ == '__main__':
  totals = []
  lines = open('so.txt').readlines()

  header = find_header(lines)
  start = find_next_separator(lines, header+1)

  while True:
    end = find_next_separator(lines, start+1)
    if end is None: break

    # Pull out block, after line of dashes.
    metrics_block = lines[start+1:end]

    # Pull out 2nd column from 1st line of metrics.
    eng_total = metrics_block[0].split()[1]
    totals.append(eng_total)

    start = end

  print totals

Вы можете использовать генератор, чтобы быть немного более питоническим:

def metric_block_iter(lines):
  start = find_next_separator(lines, find_header(lines)+1)
  while True:
    end = find_next_separator(lines, start+1)
    if end is None: break
    yield (start, end)
    start = end


if __name__ == '__main__':
  totals = []
  lines = open('so.txt').readlines()

  for (start, end) in metric_block_iter(lines):
    # Pull out block, after line of dashes.
    metrics_block = lines[start+1:end]

    # Pull out 2nd column from 1st line of metrics.
    eng_total = metrics_block[0].split()[1]
    totals.append(eng_total)

  print totals

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

Первый шаг - выяснить, где определены нужные вам данные. Затем выбросить все до этой точки. Тогда начни читать.

Если eng_tot Можно двигаться, нужно выяснить, где в блоке полезных данных он находится. Итак, прочитайте строку, entries = line.split(); location = entries.index('eng_tot'), затем прочитайте th-запись из этого местоположения в соответствующей строке в выходных данных.

Ключ в том, что вам нужно разбить свою проблему на шаги, которые, как вы знаете, вы можете сделать. Глядя на что-то новое, легко разбиться. Если вы можете просто начать что- то делать, вы обнаружите, что можете найти решение без особых проблем.

Другие вопросы по тегам