Pandas: как объединить строки, завернутые в файл журнала, в последний столбец предыдущей строки / строки? - PullRequest
0 голосов
/ 04 апреля 2020

У меня есть следующий пример файла журнала:

Timestamp : Severity : Message
2020-03-08 : INFO : First line.
2020-03-08 : INFO : child process stdout:
One
Two
Three
2020-03-08 : INFO : Last line.

ПРИМЕЧАНИЕ. В исходном файле гораздо больше столбцов и несколько знаков пунктуации.

Служба, генерирующая этот журнал, порождает дочерние процессы это может привести к сбросу их стандартного вывода (т.е. с неопределенным форматированием) в родительские журналы.

Если я попытаюсь импортировать его в Pandas, я получу следующее:

import pandas as pd
df = pd.read_csv('mini_sample.txt', sep=' : ', engine='python')

    Timestamp Severity                Message
0  2020-03-08     INFO            First line.
1  2020-03-08     INFO  child process stdout:
2         One     None                   None
3         Two     None                   None
4       Three     None                   None
5  2020-03-08     INFO             Last line.

Хотя Я хотел бы получить что-то вроде этого:

    Timestamp Severity                Message            Extra
0  2020-03-08     INFO            First line.             None
1  2020-03-08     INFO  child process stdout:  One\nTwo\nThree
2  2020-03-08     INFO             Last line.             None

Итак, строки, которые не относятся к форматированию основного журнала (то есть, из дочернего процесса 'stdout / stderr), заканчиваются дополнительным столбец (т. е. «Extra») предыдущей строки.

Кроме того, они должны сохранять свое первоначальное форматирование (т. е. символы новой строки), чтобы его можно было легко прочитать при распечатке.

1 Ответ

1 голос
/ 04 апреля 2020

Использование:

#test non datetimes in first column Timestamp
m = pd.to_datetime(df['Timestamp'], errors='coerce').notna()
#get new column by Timestamp with no datetimes
df['Extra'] = df['Timestamp'].mask(m)
#replace Timestamp to misisng values if no datetimes
df['Timestamp'] = df['Timestamp'].where(m)
#aggregate first values by first 3 columns and join by Extra column
df = df.groupby(m.cumsum()).agg({'Timestamp':'first', 
                                 'Severity':'first', 
                                 'Message':'first',
                                 'Extra': lambda x: '\n'.join(x.dropna())})
print (df)
            Timestamp Severity                Message            Extra
Timestamp                                                             
1          2020-03-08     INFO            First line.                 
2          2020-03-08     INFO  child process stdout:  One\nTwo\nThree
3          2020-03-08     INFO             Last line.                 
...