使用Openpyxl在Python中创建嵌套字典

使用Openpyxl在Python中创建嵌套字典,python,dictionary,openpyxl,Python,Dictionary,Openpyxl,试图用Python构建一个字典,该字典是使用Openpyxl循环通过Excel文件创建的,其中键是人名,值是字典项列表,其中每个键是位置,值是开始和结束的数组 以下是Excel文件: 这就是我想要的: people = { 'John':[{20:[[2,4],[3,5]]}, {21:[[2,4]]}], 'Jane':[{20:[[9,10]]},{21:[[2,4]]}] } 以下是我当前的脚本: my_file = openpyxl.load_workbook('Book2.

试图用Python构建一个字典,该字典是使用Openpyxl循环通过Excel文件创建的,其中键是人名,值是字典项列表,其中每个键是位置,值是开始和结束的数组

以下是Excel文件:

这就是我想要的:

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

我相信有一种更像蟒蛇的方法可以做到这一点,但我仍然停留在这里,在正确的方向上寻找推动。这里的结果是分析每个人和每个位置的所有dict项目的重叠开始/结束。因此,John在位置20的3.00-5.00开始与他在相同位置2.00-4.00的开始/结束重叠,您可以使用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]]}]}

看来你想得太多了;默认字典的组合应该可以做到这一点

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))

openpyxl
是一项要求吗?或者您对
pandas
解决方案感兴趣吗?Openpyxl不是一个要求。@jppIn一般来说,您应该避免在循环中操纵字典或列表之类的数据结构。由于Openpyxl提供了列式访问,因此也可以不使用
itertools.groupby
通过数据帧进行访问。