Вопрос или проблема
Следующие результаты представлены в таблице, извлеченной из JIRA, и моей программе нужно извлечь данные, чтобы включить их в Excel-таблицу.
Когда данные окружены парами вертикальных черт, это столбец, а когда только 2 вертикальные черты, это значение каждого столбца.
||Имя||Возраст||Адрес||Телефоны||размер||
| Эдвардс | 22 | Лондон | 06 45 06 06 06
06 75 85 06 06
07 85 22 15 48 | 180 см |
Я должен получить это:
| Имя | Возраст | Адрес | Телефоны | размер |
| --- | --- | --- | --- | --- |
| Эдвардс | 22 | Лондон | 06 45 06 06 \\n 06 06 75 85 06 06 \\n 07 85 22 15 48 | 180 |
| Имя | Возраст | Адрес | Телефоны | размер |
| --- | --- | --- | --- | --- |
| Эдвардс | 22 | Лондон | | 06 45 06 0606 06 75 85 06 0607 85 22 15 48180 |
но все, что там после разрывов, он помещает в ту же ячейку с другими значениями в последнем столбце
Моя функция:
def process_description_column(df):
data_dictionary = {}
for index, row in df.iterrows():
modified_text = row['Description'].replace('*', '')
description_text = ""
lines = modified_text.strip().split('\n')
in_description_section = False
line_counter = 0
for line in lines:
line = line.strip()
in_description_section, line_counter, description_text = process_line_description(
line, in_description_section, line_counter, description_text)
if '||' in line:
column_names = re.split(r'\|\|', line)
columns = [col.strip() for col in column_names if col.strip()]
for col in columns:
if col not in data_dictionary:
data_dictionary[col] = []
elif '|' in line and columns:
line_without_bar = line.replace('|', '').strip()
if '\n' in line_without_bar:
values = re.split(r'\|', line)
values = [value.strip() for value in values if value.strip()]
while len(values) < len(columns):
values.append('')
for col, value in zip(columns, values):
data_dictionary[col].append(value)
else:
if data_dictionary[columns[-1]]:
data_dictionary[columns[-1]][-1] += ' ' + line_without_bar
else:
values = re.split(r'\|', line)
values = [value.strip() for value in values if value.strip()]
if len(columns) == len(values):
for col, value in zip(columns, values):
data_dictionary[col].append(value)
else:
while len(values) < len(columns):
values.append('')
for col, value in zip(columns, values):
data_dictionary[col].append(value)
data_dictionary['Description'] = [description_text.strip()]
return data_dictionary
Я пробовал другие способы, кроме вышеупомянутого, но у меня всегда была другая проблема из-за разрывов.
Ответ или решение
Проблемы с парсингом таблиц, разделенных на несколько столбцов с пайпами в Python
Введение
В процессе извлечения данных из таблиц, разделенных символами пайпа, разработчики часто сталкиваются с проблемами, связанными с форматом представления данных. В данной статье мы рассмотрим проблему, возникающую при парсинге многоуровневых таблиц, где значения в столбцах также могут содержать переносы строк. Будем использовать представленный вами код и общее описание задачи как основной контекст.
Контекст проблемы
Из приведенных данных, извлеченных из JIRA, мы видим, что каждый элемент таблицы отделен двойными пайпами (||
), а значения отдельных столбцов — одиночными пайпами (|
). Пошаговая обработка данных требует особого внимания к элементам, которые могут включать переносы строк. Это создает трудности при правильной аллокации данных по столбцам: значения могут "слипаться" с другими данными.
Предложение решения
Ваша функция process_description_column
идеально выполняет основную задачу, но, вероятно, требует модификации обработки строк для разделения данных по нужным столбцам. Ниже представлено улучшенное решение, которое может помочь избежать проблем с разбивкой данных:
import pandas as pd
import re
def process_description_column(df):
data_dictionary = {}
for index, row in df.iterrows():
modified_text = row['Description'].replace('*', '')
description_text = ""
lines = modified_text.strip().splitlines()
columns = []
for line in lines:
line = line.strip()
# Обрабатываем заголовок таблицы
if '||' in line and not columns:
column_names = [col.strip() for col in re.split(r'\|\|', line) if col.strip()]
columns.extend(column_names)
for col in columns:
data_dictionary.setdefault(col, [])
# Обрабатываем строки с данными
elif '|' in line and columns:
values = [value.strip() for value in re.split(r'\|', line) if value.strip()]
# Если значение содержит переносы строк
if '\n' in ' '.join(values):
# Выделяем значение только для нужного столбца
description_text = ' \\n '.join(values)
else:
while len(values) < len(columns):
values.append('')
for col, value in zip(columns, values):
if data_dictionary[col]:
data_dictionary[col][-1] += ' ' + value if value else ''
else:
data_dictionary[col].append(value)
data_dictionary['Description'] = [description_text.strip()]
return data_dictionary
# Пример использования
# df = pd.DataFrame({'Description': ["||Name||Age||Address||Phones||size||\n|Edwards|22|London|06 45 06 06\n06 75 85 06 06\n07 85 22 15 48|180cm|"]})
# result = process_description_column(df)
# print(result)
Объяснение решения
- Структурирование данных: Использование
defaultdict
для предотвращения ошибок, связанных с отсутствующими значениями. - Обработка строк данных: Модифицированный регулярный анализ строки позволяет корректно обрабатывать строки, которые могут содержать переносы, добавляя соответствующие значения в правильные ячейки.
- Устранение дублирования: Корректировка логики добавления значений, чтобы избежать их слияния в одну ячейку.
Заключение
Парсинг данных, особенно из сложных форматов, таких как таблицы с многими уровнями разделителей, требует внимательности и тщательной работы с кодом. Повышая эффективность обработки данных, вы сможете извлечь нужную информацию более точно, что значительно облегчит дальнейшую работу с такими данными, как экспорт в Excel.
Не забудьте протестировать функцию на различных входных данных для выявления всех возможных краевых случаев. Надеюсь, предложенные решения помогут вам справиться с текущими проблемами.