У меня есть папка с ~ 100 000 текстовых файлов. Я пытаюсь прочитать все файлы и создать DataFrame с двумя идентификаторами столбцов и текстом. Для идентификатора я беру числа из своего имени файла, например, файл BL2334_uyhjghbvbvhf, я извлекаю все до подчеркивания, поэтому в этом примере мой идентификатор — BL2334. Перед созданием кадра данных я хотел бы извлечь только слова из Обнаруженного текста: ... Итак, в этом файле слово BUCK, NIP, Preerfal Deet Attracter.
Мой файл:
Id: 02398123-a642-4e3f-88a7
Type: LINE
Detected Text: BUCK
Confidence: 77.965172
Id: c85bbbe
Type: LINE
Detected Text: NIP
Confidence: 97.186539
Id: 28926a7a-78024c80-b9c5
Type: LINE
Detected Text: Preerfal Deet Attracter
Confidence: 47.749722
Мой код:
import os
import pandas as pd
path = r'C:\Users\example\Documents\MyFolder'
file_list = []
for (root, dirs, files) in os.walk(path, topdown=True):
file_list.append([root + "\\" + file for file in files])
def flatten(file_list):
result_list_files = []
for element in file_list:
if isinstance(element, str):
result_list_files.append(element)
else:
for element_1 in flatten(element):
result_list_files.append(element_1)
return result_list_files
result_flatten = flatten(file_list)
final_df = pd.DataFrame()
for file in result_flatten:
temp_df = pd.DataFrame()
id = file.split('\\')[-1].split('_')[0]
temp_df['id'] = [id]
temp_df['text'] = [open(file,encoding = "utf8").read()]
final_df = pd.concat([final_df, temp_df], ignore_index = True)
Я получаю вывод с двумя идентификаторами столбцов и текстом. Это занимает много времени, и в моем текстовом столбце у меня есть все из моего файла, и мне нужны только слова из Detecte Text:
Чтобы получить только части Detected Text
, я бы использовал регулярное выражение. Пример:
import re
text = """
Id: 02398123-a642-4e3f-88a7
Type: LINE
Detected Text: BUCK
Confidence: 77.965172
Id: c85bbbe
Type: LINE
Detected Text: NIP
Confidence: 97.186539
Id: 28926a7a-78024c80-b9c5
Type: LINE
Detected Text: Preerfal Deet Attracter
Confidence: 47.749722
"""
pattern = re.compile(r"Detected Text: (.*)\n")
match = pattern.findall(text) # match becomes ['BUCK', 'NIP', 'Preerfal Deet Attracter']
Одна вещь, которая делает ваш код медленнее, заключается в том, что вы продолжаете выделять новые кадры данных, а затем объединяете их. Один из способов обойти это — сначала создать словарь с помощью key = id, value = text
, а затем преобразовать его в DF с помощью метода from_dict
: документация. Или вы можете использовать список таких кортежей (id, text)
, а затем просто:
tuples = [
("id1", "some text")
("id2", "some other text")
...
]
final_df = pd.DataFrame(tuples, columns=['id', 'text'])
Извините, я не уверен, что понимаю ваше решение. Перед final_df = pd.DataFrame() мне нужно создать словарь?
@DinkoJantoš Нет, в вашем for file in result_flatten:
не создавайте df, а добавляйте в словарь или даже список кортежей ... что угодно. Затем только в конце цикла for вы конвертируете его во фрейм данных. Я обновил ответ примером.
Спасибо за помощь.
Просто расширив решение @Luca Angioioni, вы можете использовать что-то вроде:
import os
import re
data = {'id': [], 'text': []}
for (root, dirs, files) in os.walk(path):
for file in files:
data['id'].append(file.split('_')[0])
with open(os.path.join(root, file)) as f:
data['text'].append(re.findall('Detected Text: (.*)\n', f.read()))
df = pd.DataFrame(data)
где он вернет идентификатор со списком совпадений в text
для каждой строки. Вы всегда можете использовать df.explode('text')
, чтобы разбить совпадения на свои собственные строки с дублированными идентификаторами.
Если вы по какой-то причине не хотите использовать re
, вы можете заменить последнюю строку на:
data['text'].append([line.split(':')[1].strip() for line in f if line.startswith('Detected Text')])
и это тоже должно работать.
Что не так с вашим кодом?