Буду признателен за комментарии при разборе сложного текстового файла с разделителями табуляции с помощью Python - PullRequest
0 голосов
/ 19 апреля 2019

Интересно, кто-нибудь может помочь? Я новичок в Python, использую pandas и sklearn для анализа хорошо отформатированных CSV-файлов, но теперь я хочу извлечь данные для анализа из текстового файла с разделителями табуляции с более сложным форматированием, и я не совсем уверен, с чего начать.

Я сделал простой пример файла ниже. По сути, это данные временных рядов, которые фиксируют изменяющиеся количества со временем для объектов в иерархии. Таким образом, в приведенном ниже примере верхним уровнем могут быть «Все автомобили», под которыми будут подгруппы, такие как «мягкие вершины», а также объекты самого низкого уровня, которые будут отдельными машинами. Существует несколько строк заголовка, первая всегда отражает уровень и название отслеживаемой величины, но есть несколько других строк для переноса единиц измерения (обычно 3 или 4), а последняя строка заголовка также может содержать имена групп или отдельных объектов. (например, «Мягкие топы» или «BMW»). В реальных данных имеется 10 столбцов (5 показаны в примере) и около 500 дат в таблице (3 в примере). Раздел дат повторяется несколько раз (всегда одни и те же даты), создавая несколько таблиц (в примере я показываю только один повтор). Поэтому типичный файл может содержать от 200 до 500 тыс. Строк.

Я хочу извлечь определенные столбцы и вывести их в CSV-файл, где я могу работать с ними в дальнейшем.

Примером формата, с которым я имею дело, является следующий:

File Name
Date          All_Cars_MPG   All_Cars_Doors   Group_MPG   Car_MPG
              Units          Units            Units       Units
              Units          Units            Units       Units
              Units          Units            Soft Tops   BMW
Line of tab separated spaces
01-NOV-2015   32.5           4                18.2        25
01-DEC-2015   30.5           4                15.8        22
01-JAN-2016   35.0           5                19.0        26
Line of spaces or tab separated spaces
File name (same as above)
Date          Car_Doors     Car_MPG           Car_Doors   Car_Speed
              Units         Units             Units       Units
              Units         Units             Units       Units
              BMW           AUDI              AUDI        NISSAN
Line of tab separated spaces
01-NOV-2015   5             35                2           250
01-DEC-2015   5             12                8           220
01-JAN-2016   6             19                0           260

Полагаю, мне нужно перебирать строки в файлах и извлекать столбцы, необходимые для создания CSV (возможно, путем выделения имен элементов самого низкого уровня, которые в примере все начинаются с буквы C для автомобиля), но не уверен, как это настроить. Найдя строку, начинающуюся с C в строке заголовка, как лучше добавить имя объекта (из нижней строки заголовка), а затем извлечь столбец данных под ним? А после извлечения одного столбца следующий, который мне понадобится, будет, конечно, находиться в другой позиции в стеке таблиц, поэтому нельзя использовать фиксированную позицию в списке или словаре. Я не ожидаю подробного решения, но если бы кто-то мог выделить общий подход, я был бы благодарен (Расщепление? Словари?)

Я особенно заинтересован в самом низком уровне иерархии, а форма csv будет иметь дату слева, а затем столько столбцов, сколько необходимо справа, как показано ниже:

Date,Car_MPG_BMW,Car_Doors_BMW,Car_MPG_AUDI,Car_Doors_AUDI
01-NOV-2015,25,5,35,2
01-DEC-2015,22,5,23,8
01-JAN-2016,26,6,29,0

ИЗМЕНИТЬ В ДОБАВИТЬ:

Вот попытка вставить более точную версию входного файла:

    SUMMARY OF RUN                                                    
    DATE            WOPT            WOPT            WOPT            WOPT            WOPT            WOPT            WOPT            WOPT            WTHP           
                    STB             STB             STB             STB             STB             STB             STB             STB             PSIA           
                                                                    *10**3                                                                                         
                    B1A             B2              B3              B4              B5              B6              B7              B9              B1A            

     01-JAN-2046     403847.8              0        8613069.        18449.29               0               0               0               0               0             
     01-FEB-2046     403847.8              0        8633593.        18471.77               0               0               0               0               0         
     01-MAR-2046     403847.8              0        8652024.        18492.03               0               0               0               0               0         
     01-APR-2046     403847.8              0        8671890.        18514.38               0               0               0               0               0         
     01-MAY-2046     403847.8              0        8689601.        18535.93               0               0               0               0               0         
     01-JUN-2046     403847.8              0        8707051.        18558.15               0               0               0               0               0         
     01-JUL-2046     403847.8              0        8723709.        18579.61               0               0               0               0               0         
     01-AUG-2046     403847.8              0        8740806.        18601.75               0               0               0               0               0         
     01-SEP-2046     403847.8              0        8757767.        18623.84               0               0               0               0               0         
     01-OCT-2046     403847.8              0        8774027.        18645.17               0               0               0               0               0         
     01-NOV-2046     403847.8              0        8790653.        18667.15               0               0               0               0               0         
     01-DEC-2046     403847.8              0        8806563.        18688.37               0               0               0               0               0         
     01-JAN-2047     403847.8              0        8822815.        18710.24               0               0               0               0               0         

    SUMMARY OF RUN                                                    
    DATE            WTHP            WTHP            WTHP            WTHP            WTHP            WTHP            WTHP            WTHP            WTHP           
                    PSIA            PSIA            PSIA            PSIA            PSIA            PSIA            PSIA            PSIA            PSIA           
                    B2              B3              B4              B5              B6              B7              B9              B10             B16Z           

     01-JAN-2046            0              0               0               0               0               0        180.0000               0               0         
     01-FEB-2046            0              0               0               0               0               0        180.0000               0               0         
     01-MAR-2046            0              0               0               0               0               0        180.0000               0               0         
     01-APR-2046            0              0               0               0               0               0        180.0000               0               0         
     01-MAY-2046            0              0               0               0               0               0        180.0000               0               0         
     01-JUN-2046            0              0               0               0               0               0        180.0000               0               0         
     01-JUL-2046            0              0               0               0               0               0        180.0000               0               0         
     01-AUG-2046            0              0               0               0               0               0        180.0000               0               0         
     01-SEP-2046            0              0               0               0               0               0        180.0000               0               0         
     01-OCT-2046            0              0               0               0               0               0        180.0000               0               0         
     01-NOV-2046            0              0               0               0               0               0        180.0000               0               0         
     01-DEC-2046            0              0               0               0               0               0        180.0000               0               0         
     01-JAN-2047            0              0               0               0               0               0        180.0000               0               0         

А вот пример выходного файла:

DATE,WOPT_B1A,WOPT_B2,WTHP_B1A,WTHP_B2
01-JAN-2046,403847.8,0,0,0
01-FEB-2046,403847.8,0,0,0
01-MAR-2046,403847.8,0,0,0
01-APR-2046,403847.8,0,0,0
01-MAY-2046,403847.8,0,0,0
01-JUN-2046,403847.8,0,0,0
01-JUL-2046,403847.8,0,0,0
01-AUG-2046,403847.8,0,0,0
01-SEP-2046,403847.8,0,0,0
01-OCT-2046,403847.8,0,0,0
01-NOV-2046,403847.8,0,0,0
01-DEC-2046,403847.8,0,0,0
01-JAN-2047,403847.8,0,0,0

1 Ответ

0 голосов
/ 20 апреля 2019

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

Шаг 1:
Нам нужно превратить файл .txt в список списков.

def get_tab_delimited_lines(file):
    lines = []
    with open(file, 'r') as f:
        for line in f.readlines():
                line = line.split('\t') # Split by \t (TAB)
                line = [x.strip() for x in line] # Remove white space
                lines.append(line)
    return lines

Шаг 2:
Отделите тело (таблицу) от информации заголовка (столбца).

import re # This should go at the top of the file
def get_header_and_body(lines):
    # Lets seperate the header info from the body
    header_info = [] # This is the list we will return for header info
    body = [] # This is the list we will return for body info
    temp_body = []
    temp_header_info = []
    header = True
    for line in lines:
        # If the first part of the line is a date
        # in the format [a few numbers]-[a few letterss]-[a few numbers]
        # Example: 01-JAN-2046
        if re.match(r'[0-9]+-[A-Z]+-[0-9]+', line[0]): # If a date then it is the body
            header = False
            temp_body.append(line[:-1]) # The last element is always an empty '' so remove it
        else: # Else this is header info
            header = True
            if temp_body: # Append the body if we have any
                body.append(temp_body)
            temp_body = [] # Reset the temp
        if header: # If this is a header
            # This is a set of the lines we dont need. If the line
            # starts with any of these we will ignore it.
            unwanted_starts_to_a_line = {'SUMMARY OF RUN', 'STB', '', 'PSIA'}
            # We will also ignore line with things such as *18**.
            if line and line[0] not in unwanted_starts_to_a_line and not re.match(r'\*[0-9]+\*\*', line[0]):
                temp_header_info.append(line)
        else:
            if temp_header_info:
                header_info.append(temp_header_info)
            temp_header_info = []

    if temp_body:
        body.append(temp_body)
    if temp_header_info:
        header_info.append(temp_header_info)
    return header_info, body

Шаг 3:
Теперь создайте новые заголовки столбцов, которые вы хотите: Я переворачиваю header_info, потому что дата не добавляется ни к чему другому. Таким образом, я переворачиваю обе строки заголовка, упаковываю их вместе, затем я возвращаю их обратно в порядок мы хотим.

def change_to_table_headers(header_info):
    for index in range(len(header_info)):
        # print(header_info[index]) # uncomment this to see why I did the `reversed`
        # and feel free to remove the `reversed` to see what breaks.
        t = list(zip(reversed(header_info[index][0]), reversed(header_info[index][1])))
        t.reverse()
        t = ['_'.join(x) for x in t]
        header_info[index] = ['DATE'] + t

Шаг 4:
Соберите все вместе:

import pandas as pd  # This should go at the top of the file

lines = get_tab_delimited_lines('test.txt')
header_info, body = get_header_and_body(lines)
change_to_table_headers(header_info)

for index in range(len(header_info)):

    headers = header_info[index]
    df = pd.DataFrame(body[index], columns=headers)
    print(df)

Теперь, когда он находится в кадре данных, вы можете отправить его прямо на csv или сделать с ним все, что захотите.

Приложение:

Я использовал следующее в test.txt документе, чтобы проверить его.

SUMMARY OF RUN                                                    
DATE            WOPT            WOPT            WOPT            WOPT            WOPT            WOPT            WOPT            WOPT            WTHP           
                STB             STB             STB             STB             STB             STB             STB             STB             PSIA           
                                                                *10**3                                                                                         
                B1A             B2              B3              B4              B5              B6              B7              B9              B1A            

 01-JAN-2046     403847.8              0        8613069.        18449.29               0               0               0               0               0             
 01-FEB-2046     403847.8              0        8633593.        18471.77               0               0               0               0               0         
 01-MAR-2046     403847.8              0        8652024.        18492.03               0               0               0               0               0         
 01-APR-2046     403847.8              0        8671890.        18514.38               0               0               0               0               0         
 01-MAY-2046     403847.8              0        8689601.        18535.93               0               0               0               0               0         
 01-JUN-2046     403847.8              0        8707051.        18558.15               0               0               0               0               0         
 01-JUL-2046     403847.8              0        8723709.        18579.61               0               0               0               0               0         
 01-AUG-2046     403847.8              0        8740806.        18601.75               0               0               0               0               0         
 01-SEP-2046     403847.8              0        8757767.        18623.84               0               0               0               0               0         
 01-OCT-2046     403847.8              0        8774027.        18645.17               0               0               0               0               0         
 01-NOV-2046     403847.8              0        8790653.        18667.15               0               0               0               0               0         
 01-DEC-2046     403847.8              0        8806563.        18688.37               0               0               0               0               0         
 01-JAN-2047     403847.8              0        8822815.        18710.24               0               0               0               0               0         

SUMMARY OF RUN                                                    
DATE            WTHP            WTHP            WTHP            WTHP            WTHP            WTHP            WTHP            WTHP            WTHP           
                PSIA            PSIA            PSIA            PSIA            PSIA            PSIA            PSIA            PSIA            PSIA           
                B2              B3              B4              B5              B6              B7              B9              B10             B16Z           

 01-JAN-2046            0              0               0               0               0               0        180.0000               0               0         
 01-FEB-2046            0              0               0               0               0               0        180.0000               0               0         
 01-MAR-2046            0              0               0               0               0               0        180.0000               0               0         
 01-APR-2046            0              0               0               0               0               0        180.0000               0               0         
 01-MAY-2046            0              0               0               0               0               0        180.0000               0               0         
 01-JUN-2046            0              0               0               0               0               0        180.0000               0               0         
 01-JUL-2046            0              0               0               0               0               0        180.0000               0               0         
 01-AUG-2046            0              0               0               0               0               0        180.0000               0               0         
 01-SEP-2046            0              0               0               0               0               0        180.0000               0               0         
 01-OCT-2046            0              0               0               0               0               0        180.0000               0               0         
 01-NOV-2046            0              0               0               0               0               0        180.0000               0               0         
 01-DEC-2046            0              0               0               0               0               0        180.0000               0               0         
 01-JAN-2047            0              0               0               0               0               0        180.0000               0               0         

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...