2017-01-31 1 views
1

Я имею дело с плохо выложенными листами Excel, которые я пытаюсь разобрать и записать в базу данных.Как анализировать данные из листа excel со многими таблицами (используя Python, возможно, Pandas)

Каждый лист может иметь несколько таблиц. Хотя заголовок для этих возможных таблиц известен, какие таблицы собираются на любом листе, это не так, и их точное местоположение на листе (таблицы не выравниваются согласованным образом). Я добавил рисунок двух возможных макетов листов, чтобы проиллюстрировать это: This layout имеет две таблицы, а this one имеет все таблицы первого, но не в том же месте, плюс дополнительная таблица.

Что я знаю:

  1. Все возможные заголовки таблиц, поэтому каждая отдельная таблица может быть идентифицирован по его заголовкам
  2. Таблицы разделены пустыми ячейками. Они не касаются друг друга.

Мой вопрос Есть ли чистый способ справиться с этим с помощью какой-то модуль 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) 
+0

Является ли 'header1' * always * in A1? Есть ли другой шаблон (например, Always in C1 и т. Д.) Или вообще нет шаблона? Мне просто интересно, есть ли какой-либо заметный шаблон, чтобы сделать процесс проверки заголовков более эффективным. – spicypumpkin

+0

заголовок, кажется, всегда в B2. Я бы предпочел не полагаться на это всегда так, но это похоже на все файлы excel, которые я смотрел на –

+0

. Я сделал несколько сценариев, которые обрабатывают извлечение таблиц в dataframes. В ближайшее время я отправлю ссылку на репозиторий git. –

ответ

0

Это такая специфическая ситуация, которая не существует, вероятно, не «чистый» способ сделать это с готовый модуль.

Один из способов сделать это может использовать информацию заголовка, которую вы уже должны найти начальные индексы каждой таблицы, что-то вроде этого решения (Python Pandas - Read csv file containing multiple tables), но со смещением в направлении столбца.

После того, как у вас есть начальная позиция каждой таблицы, вы хотите определить ширину (либо известную априорно, либо обнаруженную, прочитав ее до следующего пустого столбца), и прочитайте эти столбцы в кадре данных до конца таблицы ,

Преимущество метода на основе индексов, а не метода на основе очереди, заключается в том, что вам не нужно повторно обнаруживать, где разделитель находится в каждой строке, или отслеживать, какие фрагменты строки принадлежат к какой таблице. Это также агностически для наличия> 2 таблицы в строке.

Смежные вопросы