使用 Openpyxl 在 Python 中创建嵌套字典
Creating nested dictionaries in Python using Openpyxl
尝试在 Python 中构建字典,这是通过使用 Openpyxl 遍历 Excel 文件创建的,其中键是人名,值是字典项列表,其中每个key是Location,value是Start和End的数组。
这是 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: 块后的行以尝试将新的 Location 字典添加到初始列表时,它会创建一个无限循环。
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 的方法可以做到这一点,但很困在这里,正在寻找正确方向的推动。这里的结果是分析每个人和每个位置重叠 Start/Ends 的所有字典项。所以 John 在位置 20 的 3.00 - 5.00 开始与他在 2.00 - 4.00
相同位置的 Start/End 重叠
您可以为此使用 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))
尝试在 Python 中构建字典,这是通过使用 Openpyxl 遍历 Excel 文件创建的,其中键是人名,值是字典项列表,其中每个key是Location,value是Start和End的数组。
这是 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: 块后的行以尝试将新的 Location 字典添加到初始列表时,它会创建一个无限循环。
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 的方法可以做到这一点,但很困在这里,正在寻找正确方向的推动。这里的结果是分析每个人和每个位置重叠 Start/Ends 的所有字典项。所以 John 在位置 20 的 3.00 - 5.00 开始与他在 2.00 - 4.00
相同位置的 Start/End 重叠您可以为此使用 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))