如何将不规则数据的多级字典转换为所需的格式

问题描述 投票:0回答:2
Dict = {'Things' : {'Car':'Lambo', 'Home':'NatureVilla', 'Gadgets':{'Laptop':{'Programs':{'Data':'Excel', 'Officework': 'Word', 'Coding':{'Python':'PyCharm', 'Java':'Eclipse', 'Others': 'SublimeText'}, 'Wearables': 'SamsungGear', 'Smartphone': 'Nexus'}, 'clothes': 'ArmaaniSuit', 'Bags':'TravelBags'}}}}



d = {(i,j,k,l,m,n): Dict[i][j][k][l][m][n]
     for i in Dict.keys()
     for j in Dict[i].keys()
     for k in Dict[j].keys()
     for l in Dict[k].keys()
     for m in Dict[l].keys()
     for n in Dict[n].keys()
     }

mux = pd.MultiIndex.from_tuples(d.keys())
df = pd.DataFrame(list(d.values()), index=mux)
print (df)

我已经做过的事情:我尝试使用pandas对这个不规则数据进行多重索引,但我在'Car'获得了KeyError。然后我尝试处理异常并试图通过它,但然后它导致语法错误。所以我可能会失去方向。如果有任何其他模块或方式,我可以索引这些不规则数据,并以某种方式将其放在表中。我有一大堆像这样的原始数据。

我想做的是:我想在QTableView中使用这些数据进行打印,这是来自PyQt5(使用GUI制作程序)。

条件:此数据每小时都会从API更新。

到目前为止我一直在想:可能是我可以将所有这些数据附加到MySQL。但是当这个数据从API更新时,只有值会改变,其余的KEYS将是相同的。但那将需要更多空间。

参考文献:How to convert a 3-level dictionary to a desired format?

How to build a MultiIndex Pandas DataFrame from a nested dictionary with lists

任何帮助将不胜感激。感谢您阅读此问题。

python pandas dictionary dataframe qtableview
2个回答
0
投票

您的数据实际上不是一个6级字典,就像您引用的3级示例中的字典一样。区别在于:您的词典具有多个不同级别的数据,例如: 'Lambo'值位于层次结构的第二层,带有键('Things','Car'),但'Eclipse'值位于层次结构的第六层,带有键('Things','Gadgets','Laptop','Programs' , '编码',“Java的)

如果你想“扁平化”你的结构,你需要决定如何处理'错过的'关键值,以获得更像“Lambo”等值的更深层次。

顺便说一下,也许它实际上并不是你问题的解决方案,也许你需要使用像TreeView这样的更合适的UI小部件来处理这种分层数据,但我会尝试直接解决你的确切问题。

不幸的是,在一个简单的dict或list comprehension语句中统一引用所有不同的级别值似乎并不容易。只要看看你的'价值提取器'(Dict[i][j][k][l][m][n])就没有i,j,k,l,m,n这样的值存在,它允许你获得'Lambo'。因为要获得一个兰博,你需要使用Dict['Things']['Car'](具有讽刺意味的是,在现实生活中,获得兰博可能也很困难:-))

解决您的任务的一种直接方法是:提取第二级数据,提取第三级数据,等等,并将它们组合在一起。例如。要提取第二级值,您可以编写如下内容:

val_level2 = {(k1,k2):Dict[k1][k2] 
   for k1 in Dict 
   for k2 in Dict[k1] 
   if isinstance(Dict[k1],dict) and 
      not isinstance(Dict[k1][k2],dict)}

但是如果你想稍后将其与六个级别值组合,则需要在关键元组中添加一些填充:

val_level2 = {(k1,k2,'','','',''):Dict[k1][k2] 
   for k1 in Dict 
   for k2 in Dict[k1] 
   if isinstance(Dict[k1],dict) and 
      not isinstance(Dict[k1][k2],dict)}

之后你可以通过以下方式将所有组合在一起:

d = {}
d.update(val_level2)
d.update(val_level3)

但通常使用分层数据最有机的方法是使用一些递归,如下所示:

def flatten_dict(d,key_prefix,max_deep):
    return [(tuple(key_prefix+[k]+['']*(max_deep-len(key_prefix))),v) 
        for k,v in d.items() if not isinstance(v,dict)] +\
        sum([flatten_dict(v,key_prefix+[k],max_deep) 
              for k,v in d.items() if isinstance(v,dict)],[])

后来用这样的代码:

d={k:v for k,v in flatten_dict(Dict,[],5)}
mux = pd.MultiIndex.from_tuples(d.keys())
df = pd.DataFrame(list(d.values()), index=mux)
df.reset_index()

我实际上用你的数据得到了这个结果:

resulting data_frame

附:根据https://www.python.org/dev/peps/pep-0008/#prescriptive-naming-conventions,我们更喜欢使用lowercase_with_underscores作为变量名,CapWords适用于类。所以src_dict会比你的Dict好得多。


0
投票

您的信息看起来很像json,这就是API返回的内容。如果是这种情况,并且你把它变成了字典,那么你最好还是使用python的json库,甚至是panda构建的read_json格式。

Pandas read json

Python's json

© www.soinside.com 2019 - 2024. All rights reserved.