【问题标题】:Converting a dict containing multiple nestet dicts into a .csv将包含多个嵌套字典的字典转换为 .csv
【发布时间】:2021-07-23 19:39:45
【问题描述】:

我在 Python 中有一个包含多个嵌套字典的字典,我想将它们写入一个 csv 文件。

字典看起来像这样:

dict = {'case1':{'variant1':{'Name':['1','2','3'],'Values':[1,2,3],'Unit':['one','two','three']}},
                 'variant2':{'Name':['1','2','3'],'Values':[1,2,3],'Unit':['one','two','three']},
        'case2':{'variant1':{'Name':['1','2','3'],'Values':[1,2,3],'Unit':['one','two','three']}},
                 'variant2':{'Name':['1','2','3'],'Values':[1,2,3],'Unit':['one','two','three']}}

因此,具有不同变体的多个案例,每个变体包含三个对应名称、值和单位的列表。 如前所述,我想将此 dict 转换为 csv 文件,理想情况下,不同情况下的变体很容易区分。由于 csv 将主要在 Excel 中使用,我将举例说明我想象它在 Excel 中的外观。理想是这样的: test_dict2csv

我知道如何将单个变体(即一组名称、值和单位)写入 csv,其代码如下所示:

keys = sorted(dict['case1']['variant1'].keys())
with open("test_output.csv", "w") as outfile:
   writer = csv.writer(outfile,delimiter=';')
   writer.writerow(keys)
   writer.writerows(zip(*[dict['case1']['variant1'][key] for key in keys]))

但我不知道如何在同一行向下添加下一个变体和案例。

如果有人有想法,我将非常感激:)

【问题讨论】:

  • 在您提供的示例输出中,您有带有 12 字段的 3 记录,因为每个列表都有 3 个元素。这是您可以对所有数据做出的假设(所有列表将具有相同数量的元素)吗?请注意,您的示例字典有两次密钥 variant2,这将如何处理?另外请不要使用dict作为变量名,因为它是一个python关键字,所以在你的sn-p代码中它是一个变量,但读起来很奇怪,因为人们期望dict意味着和做某事否则。

标签: python csv dictionary nested


【解决方案1】:

如果你想每个元素生成一个记录,每个列表一个元素,你可以先把字典展平,然后像你这样写:

import csv
from pprint import pprint

dict_data = {
    "c1": {
        "v1": {
            "Name": ["s111", "s112", "s113"],
            "Values": [111, 112, 113],
            "Unit": ["11one", "11two", "11three"],
        },
        "v2": {
            "Name": ["s121", "s122", "s123"],
            "Values": [121, 122, 123],
            "Unit": ["12one", "12two", "12three"],
        },
    },
    "c2": {
        "v1": {
            "Name": ["s211", "s212", "s213"],
            "Values": [211, 212, 213],
            "Unit": ["21one", "21two", "21three"],
        },
        "v2": {
            "Name": ["s221", "s222", "s223"],
            "Values": [221, 222, 223],
            "Unit": ["22one", "22two", "22three"],
        },
    },
}


def flatten_dict(curr_dict, curr_key=""):
    new_dict = {}
    for new_key, value in curr_dict.items():

        if curr_key == "":
            combined_key = new_key
        else:
            combined_key = curr_key + "_" + new_key

        if isinstance(value, dict):
            new_dict.update(flatten_dict(value, combined_key))
        else:
            new_dict[combined_key] = value

    return new_dict


flat = flatten_dict(dict_data)
pprint(flat)


keys = sorted(flat.keys())
with open("test_output_all.csv", "w") as outfile:
    writer = csv.writer(outfile, delimiter=";")
    writer.writerow(keys)
    writer.writerows(zip(*[flat[key] for key in keys]))

(我只是更改了 dict 以更清楚地知道哪个值是哪个,并且键名更短,结构与您的相似)。 这打印:

{'c1_v1_Name': ['s111', 's112', 's113'],
 'c1_v1_Unit': ['11one', '11two', '11three'],
 'c1_v1_Values': [111, 112, 113],
 'c1_v2_Name': ['s121', 's122', 's123'],
 'c1_v2_Unit': ['12one', '12two', '12three'],
 'c1_v2_Values': [121, 122, 123],
 'c2_v1_Name': ['s211', 's212', 's213'],
 'c2_v1_Unit': ['21one', '21two', '21three'],
 'c2_v1_Values': [211, 212, 213],
 'c2_v2_Name': ['s221', 's222', 's223'],
 'c2_v2_Unit': ['22one', '22two', '22three'],
 'c2_v2_Values': [221, 222, 223]}

在文件中:

c1_v1_Name;c1_v1_Unit;c1_v1_Values;c1_v2_Name;c1_v2_Unit;c1_v2_Values;c2_v1_Name;c2_v1_Unit;c2_v1_Values;c2_v2_Name;c2_v2_Unit;c2_v2_Values
s111;11one;111;s121;12one;121;s211;21one;211;s221;22one;221
s112;11two;112;s122;12two;122;s212;21two;212;s222;22two;222
s113;11three;113;s123;12three;123;s213;21three;213;s223;22three;223

如果您绝对需要图片中的标题, 对标题行进行一些预处理应该是可行的,以便在单独的行上打印每个嵌套级别。

干杯!

【讨论】:

    猜你喜欢
    • 2014-09-16
    • 1970-01-01
    • 1970-01-01
    • 2022-12-05
    • 1970-01-01
    • 2022-01-13
    • 2021-08-09
    • 1970-01-01
    • 2022-11-04
    相关资源
    最近更新 更多