【问题标题】:Creating a nested dictionary from a CSV file with Python with 2 levels使用 2 级 Python 从 CSV 文件创建嵌套字典
【发布时间】:2021-03-04 23:20:49
【问题描述】:

我正在努力将 csv 导入嵌套字典。 我找到了一个对我来说几乎完美的例子:

UID,BID,R
U1,B1,4
U1,B2,3
U2,B1,2

import csv

new_data_dict = {}
with open("data.csv", 'r') as data_file:
    data = csv.DictReader(data_file, delimiter=",")
    for row in data:
        item = new_data_dict.get(row["UID"], dict())
        item[row["BID"]] = int(row["R"])

        new_data_dict[row["UID"]] = item

print new_data_dict

就我而言,我还有一层嵌套要做。我的数据如下:

FID,UID,BID,R
A1,U1,B1,4
A1,U1,B2,3
A1,U2,B1,2
A2,U1,B1,4
A2,U1,B2,3
A2,U2,B1,2

结果应该是:

{"A1":{"U1":{"B1":4, "B2": 3}, "U2":{"B1":2}},
 "A2":{"U1":{"B1":4, "B2": 3}, "U2":{"B1":2}}}

我必须如何完成和更正上面发布的代码?

谢谢, 托比

【问题讨论】:

  • 你的输入数据有两次标题行
  • 这能回答你的问题吗? csv to nested JSON?
  • @BillHuang 不,因为提到的帖子不涉及 2 个级别

标签: python csv dictionary import


【解决方案1】:

如果你想简单,你可以试试这个:

import csv

new_data_dict = {}
with open("data.csv", "r") as data_file:
    data = csv.DictReader(data_file, delimiter=",")
    for row in data:
        if row["R"] != "R":
            item = new_data_dict.get(row["UID"], dict())
            item[row["BID"]] = int(row["R"])
        
            temp_dict = new_data_dict.get(row["FID"], dict())
            if row["UID"] in temp_dict:
                temp_dict[row["UID"]].update(item)
            else:
                temp_dict[row["UID"]] = item
        
            new_data_dict[row["FID"]] = temp_dict

print new_data_dict

我刚刚在分配给new_data 之前添加了一个名为temp_dict 的新字典,以便可以保留以前的值。

结果:

{'A1': {'U1': {'B1': 4, 'B2': 3}, 'U2': {'B1': 2}}, 'A2': {'U1': {'B1': 4, 'B2': 3}, 'U2': {'B1': 2}}}

【讨论】:

  • 感谢您的帮助!很乐意选择两者作为正确答案,因为两者都工作得很好。我选择了另一个,因为它是稍微优雅一点的版本。
【解决方案2】:

使用 collections.defaultdict 递归地将自己定义为默认字典,嵌套级别非常容易。

这个独立的例子(不是使用文件,而是使用行列表)演示了它:

import collections
import csv,json

data_file="""FID,UID,BID,R
A1,U1,B1,4
A1,U1,B2,3
A1,U2,B1,2
A2,U1,B1,4
A2,U1,B2,3
A2,U2,B1,2
""".splitlines()

def nesteddict():
    return collections.defaultdict(nesteddict)

new_data_dict = nesteddict()

data = csv.DictReader(data_file, delimiter=",")
for row in data:
    new_data_dict[row["FID"]][row["UID"]][row["BID"]] = row["R"]

# dump as json to have a clean, indented representation
print(json.dumps(new_data_dict,indent=2))

结果:

{
  "A1": {
    "U1": {
      "B1": "4",
      "B2": "3"
    },
    "U2": {
      "B1": "2"
    }
  },
  "A2": {
    "U1": {
      "B1": "4",
      "B2": "3"
    },
    "U2": {
      "B1": "2"
    }
  }
}

“神奇”行是这样的:

def nesteddict():
    return collections.defaultdict(nesteddict)

每次调用字典 nesteddict 中缺少一个键时,都会创建一个具有相同属性的默认字典(在旧的 StackOverflow 答案中看到:Nested defaultdict of defaultdict

然后创建关卡或更新它们只需:

new_data_dict[row["FID"]][row["UID"]][row["BID"]] = row["R"]

【讨论】:

  • 感谢您的帮助!!!工作得很好。 :) 我不明白的是,当一个键不在循环部分中时,如何调用nesteddict?或者你的意思是如果我用不同的输入文件运行程序?
猜你喜欢
  • 1970-01-01
  • 2012-08-26
  • 1970-01-01
  • 1970-01-01
  • 2017-07-25
  • 2021-02-20
  • 2022-11-05
  • 2021-08-13
  • 2012-02-10
相关资源
最近更新 更多