Использование Python для анализа строки заголовка из файла с уникальной техникой печати заголовка (расширение .inp) - PullRequest
0 голосов
/ 17 мая 2018

Я хочу использовать Python для разбора кадра данных из файла (для тех, кто мог бы использовать его входной / входной файл модели SWMM).Заголовок файла печатается довольно уникальным способом, что затрудняет его полный анализ.Пример кадра данных с проблемным заголовком) Я пытаюсь прочитать из файла:

;;                                                 Param    
;;Node           Parameter        Time Series      Type     
;;-------------- ---------------- ---------------- -------- 
80408            FLOW             80408            FLOW     
81009            FLOW             81009            FLOW     
82309            FLOW             82309            FLOW     

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

Все, что мне удалось сделать, - это взять самую нижнюю строку в качестве заголовка.

 with open(inp_fname, 'r') as f:
        for line in f:
               headers = re.split("\s{2,}", line.replace(';',"").strip())

Ответы [ 2 ]

0 голосов
/ 18 мая 2018

Та же идея, что и в коде @ tdelaney, сделана более краткой:

from itertools import takewhile
import re
import pandas as pd

def make_dataframe(filename):
    with open(filename) as fp:
        div = []
        headers = list(takewhile(
            lambda x: not x.startswith(';;-') or div.append(x), fp))
        colspecs = [m.span() for m in re.compile("-+").finditer(div[0])]
        headers = [
            re.sub(" +", " ", " ".join(hl[lo : hi] for hl in headers)).strip()
            for lo, hi in colspecs]
        d = pd.read_fwf(fp, header = None,
            colspecs = [(lo - 2, hi - 2) for lo, hi in colspecs])
    d.columns = headers
    return d

print(make_dataframe('test.txt'))
0 голосов
/ 18 мая 2018

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

import pandas as pd
import re

# write a test file...
open('test.txt', 'w').write("""\
;;                                                 Param    
;;Node           Parameter        Time Series      Type     
;;-------------- ---------------- ---------------- -------- 
80408            FLOW             80408            FLOW     
81009            FLOW             81009            FLOW     
82309            FLOW             82309            FLOW     """)


def make_dataframe(filename):
    with open('test.txt') as fp:
        # grab header
        headers = []
        for line in fp:
            if not line.startswith(';;-'):
                # header line, swap '  ' for ';;' to maintain len
                headers.append('  ' + line[2:-1])
            else:
                break
        else:
            print("ERROR: Header separator not found")
            return None

        # end of header, convert '----' separators to field lengths
        field_lens = [len(m)+1 for m in re.findall(r"\-+", '--' + line[2:-1])]

        # flatten multiline column names
        start = 0
        pd_header = []
        for f_len in field_lens:
            pd_header.append(' '.join(field.strip()
                for field in (h[start:start+f_len] for h in headers)
                if field.strip()))
            start += f_len

        # read fix length columns
        df = pd.read_fwf(fp, header=None, names=pd_header, widths=field_lens,
            index_col=False)
        return df

df = make_dataframe('test.txt')
print(df)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...