Создание вложенных словарей в Python с использованием Openpyxl

1

Попытка создать словарь в Python, созданный путем циклического перемещения файла Excel с помощью Openpyxl, где ключ - это имя человека, а значение - это список элементов словаря, где каждый ключ является местоположением, а значение представляет собой массив Начало и конец.

Вот файл Excel:

Изображение 174551

И вот что я хочу:

people = {
  'John':[{20:[[2,4],[3,5]]}, {21:[[2,4]]}],
  'Jane':[{20:[[9,10]]},{21:[[2,4]]}]
}

Вот мой текущий скрипт:

my_file = openpyxl.load_workbook('Book2.xlsx', read_only=True)
ws = my_file.active

people = {}
for row in ws.iter_rows(row_offset=1):
  a = row[0] # Name
  b = row[1] # Date
  c = row[2] # Start
  d = row[3] # End
  if a.value:  # Only operate on rows that contain data 
    if a.value in people.keys():  # If name already in dict
      for k, v in people.items():
        for item in v:
          #print(item)
          for x in item:
            if x == int(b.value):
              print(people[k])
              people[k][0][x].append([c.value,d.value])
            else:
              #people[k].append([c.value,d.value])  # Creates inf loop
    else:
      people[a.value] = [{b.value:[[c.value,d.value]]}]

Что успешно создает это:

{'John': [{20: [[2, 4], [9, 10]]}], 'Jane': [{20: [[9, 10]]}]}

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

if x == int(b.value):
   people[k][0][x].append([c.value,d.value])
else:
   #people[k].append([c.value,d.value])  # Creates inf loop

Я уверен, что здесь есть более Pythonic способ сделать это, но довольно застрял здесь и ищет подталкивание в правильном направлении. Результатом здесь является анализ всех элементов dict для перекрытия Start/Ends на человека и каждого места. Итак, John Start 3.00 - 5.00 в позиции 20 перекрывается с его Start/End в том же месте 2.00 - 4.00

  • 0
    Является ли openpyxl требованием? Или вас заинтересует решение для pandas ?
  • 1
    Openpyxl не является обязательным требованием .. @jpp jpp
Показать ещё 1 комментарий
Теги:
dictionary
openpyxl

2 ответа

1
Лучший ответ

Кажется, вы переусердствовали это; комбинация словарей по умолчанию должна делать трюк.

from collections import defaultdict
person = defaultdict(dict)

for row in ws.iter_rows(min_row=2, max_col=4):
    p, l, s, e = (c.value for c in row)
    if p not in person:
        person[p] = defaultdict(list)
    person[p][l].append((s, e))
1

Для этого вы можете использовать библиотеку Pandas. Ядром этого решения является вложенное понимание словаря, каждый из которых использует groupby. Вы можете, как показано ниже, использовать функцию по уходу за гнездом, чтобы облегчить читаемость/обслуживание.

import pandas as pd

# define dataframe, or df = pd.read_excel('file.xlsx')
df = pd.DataFrame({'Name': ['John']*3 + ['Jane']*2,
                   'Location': [20, 20, 21, 20, 21],
                   'Start': [2.00, 3.00, 2.00, 9.00, 2.00],
                   'End': [4.00, 5.00, 4.00, 10.00, 4.00]})

# convert cols to integers
int_cols = ['Start', 'End']
df[int_cols] = df[int_cols].apply(pd.to_numeric, downcast='integer')

# define inner dictionary grouper and split into list of dictionaries
def loc_list(x):
    d = {loc: w[int_cols].values.tolist() for loc, w in x.groupby('Location')}
    return [{i: j} for i, j in d.items()]

# define outer dictionary grouper
people = {k: loc_list(v) for k, v in df.groupby('Name')}

{'Jane': [{20: [[9, 10]]}, {21: [[2, 4]]}],
 'John': [{20: [[2, 4], [3, 5]]}, {21: [[2, 4]]}]}
  • 0
    Так как openpyxl предоставляет колоночный доступ, это также возможно без прохождения через itertools.groupby просто используя itertools.groupby .

Ещё вопросы

Сообщество Overcoder
Наверх
Меню