Сгруппировать данные .txt в фрейм данных - PullRequest
0 голосов
/ 24 января 2019

У меня есть файл .txt с такими данными:

[12.06.17, 13:18:36] Name1: Test test test
[12.06.17, 13:20:20] Name2 ❤️: blabla
[12.06.17, 13:20:44] Name2 ❤️: words words words
words
words
words
[12.06.17, 13:29:03] Name1: more words more words
[12.06.17, 13:38:52] Name3 Surname Nickname: ??
[12.06.17, 13:40:37] Name1: message?

Обратите внимание, что перед сообщением может быть несколько имен, а также могут появиться многострочные сообщения.Я уже много раз пытался за последние дни разбить данные на группы «дата», «время», «имя», «сообщение».

Мне удалось выяснить, что регулярное выражение

(.)(\d+\.\d+\.\d+)(,)(\s)(\d+:\d+:\d+)(.)(\s)([^:]+)(:)

может захватить все до сообщения (ср .: https://regex101.com/r/hQlgeM/3). Но я не могу понять, как добавить сообщение, чтобы многострочные сообщения были сгруппированы в предыдущее сообщение.

Наконец: если я смогу захватить каждую группу из .txt с помощью регулярных выражений, как я могу фактически передать каждую группу в отдельный столбец. Я смотрел на примеры за последние три дня, но я все еще не могу понятькак окончательно создать этот фрейм данных.

Код, с которым я пытался работать:

df = pd.read_csv('chat.txt', names = ['raw'])

data = df.iloc[:,0]

re.match(r'\[([^]]+)\] ([^:]+):(.*)', data)

Еще одна попытка, которая не сработала:

input_file = open("chat.txt", "r", encoding='utf-8')

content = input_file.read()

df = pd.DataFrame(content, columns = ['raw'])

df['date'] = df['raw'].str.extract(r'^(.)(\d+\.\d+\.\d+)', expand=True)

df['time'] = df['raw'].str.extract(r'(\s)(\d+:\d+:\d+)', expand=True)

df['name'] = df['raw'].str.extract(r'(\s)([^:]+)(:)', expand=True)

df['message'] = df['raw'].str.extract(r'^(.)(?<=:).*$', expand=True)

df

Ответы [ 2 ]

0 голосов
/ 26 января 2019

Вот решение, которое я понял, работает в моем случае. Проблема заключалась в том, что я использовал read_csv (), когда это TXT-данные. Также мне нужно было использовать регулярные выражения для построения моего формата, прежде чем переходить в панд:

import re
import pandas as pd

chat = open('chat.txt').read()
pattern = r'(?s)\[(?P<date>\d+(?:\.\d+){2}),\s(?P<time>\d+(?::\d+){2})]\s(?P<name>[^:]+):(?P<message>.*?)(?=\[\d+\.\d+\.\d+,\s\d+:\d+:\d+]|\Z)'

for row in re.findall(pattern, chat):
    row

df = pd.DataFrame(re.findall(pattern, chat), columns=['date', 'time', 'name', 'message'])

print (df.tail)
0 голосов
/ 24 января 2019

Полное решение будет выглядеть как

import pandas as pd
import io, re

file_path = 'chat.txt'
rx = re.compile(r'\[(?P<date>\d+(?:\.\d+){2}),\s(?P<time>\d+(?::\d+){2})]\s(?P<name>[^:]+):(?P<message>.*)')
col_list = []
date = time = name = message = ''

with io.open(file_path, "r", encoding = "utf-8", newline="\n") as sr:
    for line in sr:
        m = rx.match(line)
        if m:
            col_list.append([date, time, name, message])
            date = m.group("date")
            time = m.group("time")
            name = m.group("name")
            message = m.group("message")
        else:
            if line:
                message += line

df = pd.DataFrame(col_list, columns=['date', 'time', 'name', 'message'])

Детали шаблона

  • \[ - [ char
  • (?P<date>\d+(?:\.\d+){2}) - группа «дата»: 1+ цифр, а затем два повторения . и две цифры
  • ,\s - , и пробел
  • (?P<time>\d+(?::\d+){2}) - группа«время»: 1+ цифр, а затем два повторения : и две цифры
  • ]\s - ] и пробел
  • (?P<name>[^:]+) - Группа «name»: однаили больше символов, отличных от :
  • : - двоеточие
  • (?P<message>.*) - Групповое «сообщение»: любые 0+ символов, как можно больше, до концаline.

Затем логика выглядит следующим образом:

  • Строка считывается и проверяется по шаблону
  • Если есть совпадение,четыре переменные - дата, время, имя и сообщение - детали инициализируются
  • Если следующая строка не соответствует шаблону, она считается частью сообщения и, таким образом, добавляется к message переменной.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...