Python:将嵌套字典写入 CSV

Posted

技术标签:

【中文标题】Python:将嵌套字典写入 CSV【英文标题】:Python: Writing Nested Dictionary to CSV 【发布时间】:2015-06-06 16:20:26 【问题描述】:

我正在尝试将嵌套字典写入 .csv 文件。这是一个简单的例子:

import csv
import itertools

fields = [ 'org', '2015', '2014', '2013' ]
dw     =  'orgname1':  '2015' : 2, '2014' : 1, '2013' : 1 ,
           'orgname2':  '2015' : 1, '2014' : 2, '2013' : 3 ,
           'orgname3':  '2015' : 1, '2014' : 3, '2013' : 1 
        

with open("test_output.csv", "wb") as f:
    w = csv.writer( f )
    years = dw.values()[0].keys()
    for key in dw.keys():
        w.writerow([key, [dw[key][year] for year in years]])

这给我一个包含两列的表:第一列包含orgname;第二个包含 [2, 1, 1] (或子字典中的相应值)。我想要一个有四列的表格:一列用于orgname,然后三列用于对应的列表元素。

【问题讨论】:

dicts 没有顺序,所以你马上就有麻烦了 @PadraicCunningham 同意了。然而,他的钥匙似乎是按照字典顺序排列的。因此,他仍然可以通过对 dw.keys() 进行排序然后对其进行迭代来使其工作。 【参考方案1】:

我认为这可能是一种更简单的方法:

import csv

fields = [ 'org', '2015', '2014', '2013' ]
dw     =  'orgname1':  '2015' : 2, '2014' : 1, '2013' : 1 ,
           'orgname2':  '2015' : 1, '2014' : 2, '2013' : 3 ,
           'orgname3':  '2015' : 1, '2014' : 3, '2013' : 1 
        

with open("test_output.csv", "w") as csv_file:
  csvwriter = csv.writer(csv_file)
  csvwriter.writerow(['org', '2015', '2014', '2013'])

  for org in dw:
     csvwriter.writerow(org, dw[org]['2015'], dw[org]['2014'], dw[org]['2013'])

【讨论】:

在最后一行中缺少括号以使其工作【参考方案2】:

使用 DictWriter 无需预先对字段进行排序,因为w.writerow() 将确保正确的顺序。但是对项目本身进行排序确实很有意义。

所以综合以上所有建议并从中挑选出最好的,我会想出以下代码:

import csv
import itertools

def mergedict(a,b):
    a.update(b)
    return a

fields = [ 'org', '2015', '2014', '2013' ]
dw     =  'orgname1':  '2015' : 2, '2014' : 1, '2013' : 1 ,
           'orgname2':  '2015' : 1, '2014' : 2, '2013' : 3 ,
           'orgname3':  '2015' : 1, '2014' : 3, '2013' : 1 
        

with open("test_output.csv", "wb") as f:
    w = csv.DictWriter( f, fields )
    w.writeheader()
    for k,d in sorted(dw.items()):
        w.writerow(mergedict('org': k,d))

我添加了一个很小的 ​​mergedict() 函数,使其成为更下方的单线。

【讨论】:

【参考方案3】:

使用DictWriter 和标头的替代实现

import csv
import itertools

fields = [ 'org', '2015', '2014', '2013' ]
dw     =  'orgname1':  '2015' : 2, '2014' : 1, '2013' : 1 ,
           'orgname2':  '2015' : 1, '2014' : 2, '2013' : 3 ,
           'orgname3':  '2015' : 1, '2014' : 3, '2013' : 1 
        

with open("test_output.csv", "wb") as f:
    w = csv.DictWriter(f, fields)
    w.writeheader()
    for k in dw:
        w.writerow(field: dw[k].get(field) or k for field in fields)

输出:

org,2015,2014,2013
orgname1,2,1,1
orgname3,1,3,1
orgname2,1,2,3

【讨论】:

我最喜欢您的回答,直截了当:) 您可以考虑按其键对dw 进行排序,因为在您的输出中,组织名称的顺序已从输入中改变。使用sorted(dw.items()) 解决了这个问题 亲爱的 Python 3 用户,他们不想像我刚才所做的那样让自己感到尴尬,因为您只需将 open("test_output.csv", "wb") 切换为 open("test_output.csv", "w", newline=''),上述解决方案就可以了完美无缺。否则你会得到一个a bytes-like object is required, not 'str' when writing to a file' 。不要像我一样尝试将整个字典编码为ascii 如果我的任何键的值为 0,那么如果 2015:0 用于 orgname1,我将键作为值,如 orgname1,orgname1,1,1。所以任何解决方案。 @Łukasz Rogalski【参考方案4】:

这看起来像是DictWriter 的工作:

import csv
import itertools
import sys

fields = [ 'org', '2015', '2014', '2013' ]
dw     =  'orgname1':  '2015' : 2, '2014' : 1, '2013' : 1 ,
           'orgname2':  '2015' : 1, '2014' : 2, '2013' : 3 ,
           'orgname3':  '2015' : 1, '2014' : 3, '2013' : 1 
        

w = csv.DictWriter( sys.stdout, fields )
for key,val in sorted(dw.items()):
    row = 'org': key
    row.update(val)
    w.writerow(row)

【讨论】:

实际上你应该得到最好的评论,因为你是第一个完整的解决方案,我喜欢你使用 dicts 更新功能的方式。我在一个单独的函数中对其进行了调整,以便之后将其保持为一个衬里。所以我的答案几乎是你的,改为文件输出并添加标题:)【参考方案5】:

变化:

w.writerow([key, [dw[key][year] for year in years]])

收件人:

w.writerow([key] + [dw[key][year] for year in years])

否则,您尝试将 [orgname1, [2, 1, 1]] 之类的内容写入 csv,而您的意思是 [orgname1, 2, 1, 1]

正如 Padraic 所说,您可能需要将 years = dw.values()[0].keys() 更改为 years = sorted(dw.values()[0].keys())years = fields[1:] 以避免随机行为。

【讨论】:

如果您按照其他答案中的建议使用 DictWriter,则无需对年份进行排序 @hexereisoftware 是的,但现在只是复制。

以上是关于Python:将嵌套字典写入 CSV的主要内容,如果未能解决你的问题,请参考以下文章

如何将嵌套字典写入json

如何将带有嵌套字典的列表写入 csv 文件?

将 Python 字典写入 CSV

将嵌套字典写入 plist (Swift) 时的类型问题

将数组写入csv python(一列)

将多个列表写入 csv Python