bkb*_*lly 5 python dictionary structure
我正在寻找一种在python中动态制作基于所需结构的字典的方法。
我有以下数据:
{'weather': ['windy', 'calm'], 'season': ['summer', 'winter', 'spring', 'autumn'], 'lateness': ['ontime', 'delayed']}
Run Code Online (Sandbox Code Playgroud)
我给出了我希望它们像的结构:
['weather', 'season', 'lateness']
Run Code Online (Sandbox Code Playgroud)
并最终以这种格式获取数据:
{'calm': {'autumn': {'delayed': 0, 'ontime': 0},
'spring': {'delayed': 0, 'ontime': 0},
'summer': {'delayed': 0, 'ontime': 0},
'winter': {'delayed': 0, 'ontime': 0}},
'windy': {'autumn': {'delayed': 0, 'ontime': 0},
'spring': {'delayed': 0, 'ontime': 0},
'summer': {'delayed': 0, 'ontime': 0},
'winter': {'delayed': 0, 'ontime': 0}}}
Run Code Online (Sandbox Code Playgroud)
这是我为实现这一目标而想到的手动方式:
dtree = {}
for cat1 in category_cases['weather']:
dtree.setdefault(cat1, {})
for cat2 in category_cases['season']:
dtree[cat1].setdefault(cat2, {})
for cat3 in category_cases['lateness']:
dtree[cat1][cat2].setdefault(cat3, 0)
Run Code Online (Sandbox Code Playgroud)
你能想出一种方法来改变我写的结构并得到想要的结果吗?请记住,结构可能不会每次都具有相同的大小。
此外,如果您想到除字典之外的另一种方式可以访问结果,它也适用于我。
如果您不回避使用外部包,pandas.DataFrame可能是一个可行的候选者,因为看起来您将使用一个表:
import pandas as pd
df = pd.DataFrame(
index=pd.MultiIndex.from_product([d['weather'], d['season']]),
columns=d['lateness'], data=0
)
Run Code Online (Sandbox Code Playgroud)
结果:
ontime delayed
windy summer 0 0
winter 0 0
spring 0 0
autumn 0 0
calm summer 0 0
winter 0 0
spring 0 0
autumn 0 0
Run Code Online (Sandbox Code Playgroud)
您可以通过索引轻松进行更改:
df.loc[('windy', 'summer'), 'ontime'] = 1
df.loc['calm', 'autumn']['delayed'] = 2
# Result:
ontime delayed
windy summer 1 0
winter 0 0
spring 0 0
autumn 0 0
calm summer 0 0
winter 0 0
spring 0 0
autumn 0 2
Run Code Online (Sandbox Code Playgroud)
如果您始终使用列的最后一个键,则可以动态构建表,假设您的键采用所需的插入顺序:
df = pd.DataFrame(
index=pd.MultiIndex.from_product(list(d.values())[:-1]),
columns=list(d.values())[-1], data=0
)
Run Code Online (Sandbox Code Playgroud)
由于您对 感兴趣pandas,考虑到您的结构,我还建议您仔细阅读MultiIndex 和 Advance Indexing,只是为了了解如何处理数据。这里有些例子:
# Gets the sum of 'delayed' items in all of 'calm'
# Filters all the 'delayed' data in 'calm'
df.loc['calm', 'delayed']
# summer 5
# winter 0
# spring 0
# autumn 2
# Name: delayed, dtype: int64
# Apply a sum:
df.loc['calm', 'delayed'].sum()
# 7
# Gets the mean of all 'summer' (notice the `slice(None)` is required to return all of the 'calm' and 'windy' group)
df.loc[(slice(None), 'summer'), :].mean()
# ontime 0.5
# delayed 2.5
# dtype: float64
Run Code Online (Sandbox Code Playgroud)
它绝对非常方便且用途广泛,但在您深入了解它之前,您可能肯定想先阅读一下,该框架可能需要一些时间来适应。
否则,如果你仍然喜欢dict,那也没有什么问题。这是一个基于给定键生成的递归函数(假设您的键处于所需的插入顺序):
def gen_dict(d, level=0):
if level >= len(d):
return 0
key = tuple(d.keys())[level]
return {val: gen_dict(d, level+1) for val in d.get(key)}
gen_dict(d)
Run Code Online (Sandbox Code Playgroud)
结果:
{'calm': {'autumn': {'delayed': 0, 'ontime': 0},
'spring': {'delayed': 0, 'ontime': 0},
'summer': {'delayed': 0, 'ontime': 0},
'winter': {'delayed': 0, 'ontime': 0}},
'windy': {'autumn': {'delayed': 0, 'ontime': 0},
'spring': {'delayed': 0, 'ontime': 0},
'summer': {'delayed': 0, 'ontime': 0},
'winter': {'delayed': 0, 'ontime': 0}}}
Run Code Online (Sandbox Code Playgroud)