Я имею дело с плохо выложенными листами Excel, которые я пытаюсь разобрать и записать в базу данных.Как анализировать данные из листа excel со многими таблицами (используя Python, возможно, Pandas)
Каждый лист может иметь несколько таблиц. Хотя заголовок для этих возможных таблиц известен, какие таблицы собираются на любом листе, это не так, и их точное местоположение на листе (таблицы не выравниваются согласованным образом). Я добавил рисунок двух возможных макетов листов, чтобы проиллюстрировать это: This layout имеет две таблицы, а this one имеет все таблицы первого, но не в том же месте, плюс дополнительная таблица.
Что я знаю:
- Все возможные заголовки таблиц, поэтому каждая отдельная таблица может быть идентифицирован по его заголовкам
- Таблицы разделены пустыми ячейками. Они не касаются друг друга.
Мой вопрос Есть ли чистый способ справиться с этим с помощью какой-то модуль Python, таких как панды?
Мой текущий подход:
Я в настоящее время преобразования в .csv и разбора каждой строки. Я разделяю каждую строку вокруг пустых ячеек и обрабатываю первую часть строки (должен принадлежать самой левой таблице). Остальная часть строки помещается в очередь и затем обрабатывается таким же образом. Затем я прочитал это first_part
и проверьте, не является ли это строкой заголовка. Если это так, я использую его для определения таблицы, с которой я имею дело (она хранится в глобальном current_df
). Последующие строки, которые не являются строками заголовка, подаются в эту таблицу (здесь я использую pandas.DataFrame
для моих таблиц).
код до сих пор находится ниже (в основном неполной и непроверенной, но он должен передать выше подход):
class DFManager(object): # keeps track of current table and its headers
current_df = None
current_headers = []
def set_current_df(self, df, headers):
self.current_headers = headers
self.current_df = df
def split_row(row, separator):
while row and row[0] == separator:
row.pop(0)
while row and row[-1] == separator:
row.pop()
if separator in row:
split_index = row.index(separator)
return row[:split_index], row[split_index:]
else:
return row, []
def process_df_row(row, dfmgr):
df = df_with_header(row) # returns the dataframe with these headers
if df is None: # is not a header row, add it to current df
df = dfmgr.current_df
add_row_to_df(row, df)
else:
dfmgr.set_current_df(df, row)
# this is passed the Excel sheet
def populate_dataframes(xl_sheet):
dfmgr = DFManager()
row_queue = Queue()
for row in xl_sheet:
row_queue.put(row)
for row in iter(row_queue.get, None):
if not row:
continue
first_part, remainder = split_row(row)
row_queue.put(remainder)
process_df_row(first_part, dfmgr)
Является ли 'header1' * always * in A1? Есть ли другой шаблон (например, Always in C1 и т. Д.) Или вообще нет шаблона? Мне просто интересно, есть ли какой-либо заметный шаблон, чтобы сделать процесс проверки заголовков более эффективным. – spicypumpkin
заголовок, кажется, всегда в B2. Я бы предпочел не полагаться на это всегда так, но это похоже на все файлы excel, которые я смотрел на –
. Я сделал несколько сценариев, которые обрабатывают извлечение таблиц в dataframes. В ближайшее время я отправлю ссылку на репозиторий git. –