【问题标题】:How to convert Multilevel Dictionary with Irregular Data to Desired Format如何将具有不规则数据的多级字典转换为所需格式
【发布时间】:2018-08-09 16:45:12
【问题描述】:
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)

我已经做了什么: 我尝试使用熊猫对这个不规则数据进行多索引,但在“汽车”处出现 KeyError。然后我尝试处理异常并尝试通过它,但随后导致语法错误。所以可能是我迷失了方向。如果有任何其他模块或方法,我可以索引这些不规则数据并以某种方式将其放入表中。我有一大堆这样的原始数据。

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

条件: 这些数据每小时都会通过 API 更新。

到目前为止我的想法: 也许我可以将所有这些数据附加到 MySQL。但是当这些数据从 API 更新时,只有 Values 会改变,其余的 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


    【解决方案1】:

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

    如果您想“扁平化”您的结构,您将需要决定如何处理“缺失”的关键值,以获取更深层次的值,例如“Lambo”。

    顺便说一句,也许它实际上并不能解决您的问题,也许您需要使用更合适的 UI 小部件(如 TreeView)来处理此类分层数据,但我会尝试直接 解决您的确切问题。

    不幸的是,在一个简单的 dict 或列表理解语句中统一引用所有不同级别的值似乎并非易事。 只要看看你的“价值提取器”(Dict[i][j][k][l][m][n]),i、j、k、l、m、n 不存在这样的值,它可以让你得到一个“兰博”。因为要获得兰博,您只需要使用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()
    

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

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

    【讨论】:

    • 你的回答让我逻辑思考了一遍又一遍。展平可能对我的数据有帮助,因为我也需要对其进行排序。您的答案似乎非常适合我正在寻找的内容。谢谢你。我会继续在 Python 中修修补补!
    • 感谢您的反馈。它会激励我去帮助别人。 Python很棒,如果你继续使用它,你就没有机会不爱上它:-)
    【解决方案2】:

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

    Pandas read json

    Python's json

    【讨论】:

    • 感谢您的回答。我浏览了其他答案,我发现我需要展平数据。另外,它也允许排序。但我也很想探索 json 模块来处理更多数据。
    猜你喜欢
    • 1970-01-01
    • 2021-01-01
    • 2018-12-24
    • 1970-01-01
    • 2017-08-26
    • 1970-01-01
    • 2023-03-16
    • 2021-04-25
    • 1970-01-01
    相关资源
    最近更新 更多