在字典中获取决策树

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)

你能想出一种方法来改变我写的结构并得到想要的结果吗?请记住,结构可能不会每次都具有相同的大小。

此外,如果您想到除字典之外的另一种方式可以访问结果,它也适用于我。

r.o*_*ook 4

如果您不回避使用外部包,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)