将字典列表写入CSV Python

6
假设我有以下字典数据集列表:
data_set = [
    {'Active rate': [0.98, 0.97, 0.96]},
    {'Operating Expense': [3.104, 3.102, 3.101]}
]

我需要迭代字典列表,将键作为列标题,将值作为行,然后将其写入CSV文件。
Active rate    Operating Expense
0.98           3.104
0.97           3.102
0.96           3.101

这是我尝试过的方法

data_set = [
    {'Active rate': [0.98, 0.931588, 0.941192]},
    {'Operating Expense': [3.104, 2.352, 2.304]}
]

import csv

with open('names.csv', 'w') as csvfile:
    fieldnames = ['Active rate', 'Operating Expense']
    writer = csv.DictWriter(csvfile, fieldnames=fieldnames)

    writer.writeheader()
    writer.writerow({'Active rate': 0.98, 'Operating Expense': 3.102})
    writer.writerow({'Active rate': 0.97, 'Operating Expense': 3.11})
    writer.writerow({'Active rate': 0.96, 'Operating Expense': 3.109})

为了简洁起见,我将键减少到2个,值的列表减少到3个。
如何解决这个问题?
谢谢

4
实际问题是什么? - thefourtheye
你想知道如何自动编写每一行而不是手动将值放在一起吗? - albert
是的,我需要知道如何自动编写每一行。 - PyAn
5个回答

3
以下方法适用于您提供的数据结构:
import csv

data_set = [
    {'Active rate': [0.98, 0.97, 0.96]},
    {'Operating Expense': [3.104, 3.102, 3.101]}
]

fieldnames = ['Active rate', 'Operating Expense']
rows = []

for field in fieldnames:
    for data in data_set:
        try:
            rows.append(data[field])
            break
        except KeyError, e:
            pass

with open('names.csv', 'wb') as f_output:
    csv_output = csv.writer(f_output)
    csv_output.writerow(fieldnames)
    csv_output.writerows(zip(*rows))

给您以下CSV输出文件:
Active rate,Operating Expense
0.98,3.104
0.97,3.102
0.96,3.101

3
d1 = {'Active rate': [0.98, 0.931588, 0.941192]}
d2 = {'Operating Expense': [3.104, 2.352, 2.304]}

with open('names.csv', 'w') as csvfile:
    fieldnames = zip(d1, d2)[0]
    writer = csv.DictWriter(csvfile, fieldnames=fieldnames)
    writer.writeheader()

    for row in zip(d1['Active rate'], d2['Operating Expense']):
        writer.writerow(dict(zip(fieldnames, row)))

为了提高性能,根据列表的长度,您可能需要使用itertools.izip而不是zip

1
itertools.izip确实是处理大型数据集的好建议。(由于索引,用它来替换 zip(d1, d2)[0] 可能会导致一些问题,但这不难解决。 - Bruno

3

(这种方法的缺点是需要使用外部库,但是)

pandas已经提供了非常强大和简单的工具处理csv文件。您可以使用to_csv

请注意,您的数据结构布局不太合适,因此我们首先将其转换为更直观的结构。

data_set2 = { x.keys()[0] : x.values()[0] for x in data_set }

import pandas as pd
df = pd.DataFrame(data_set2)
df.to_csv('names.csv', index = False)

1
有人可能已经点了踩,你只能希望他们回来检查一下。 - Bruno

2
data_set = [
    {'Active rate': [0.98, 0.97, 0.96]},
    {'Operating Expense': [3.104, 3.102, 3.101]}
]

首先,我想简单地评论一下,您的初始数据结构可能没有意义。您使用了一个字典列表,但每个字典似乎只使用了一个键,这似乎背离了它的目的。

其他更合理的数据结构可能是这样的(其中每个字典结构用于一个标签/值对,就像您当前使用的方式一样,但至少字典用于告诉标签和值):

data_set = [
    {'label': 'Active rate', 'values': [0.98, 0.97, 0.96]},
    {'label': 'Operating Expense', 'values': [3.104, 3.102, 3.101]}
]

或者,更好的选择是使用 OrderedDict,它不仅可以保持您初始数据集的顺序,还能获得键/值映射的好处:

from collections import OrderedDict
data_set = OrderedDict()
data_set['Active rate'] = [0.98, 0.97, 0.96]
data_set['Operating Expense'] = [3.104, 3.102, 3.101]

当然,我们并不总是能选择我们得到的数据结构,所以假设你无法更改它。那么你的问题就变成了从初始数据集中交换行和列的角色。实际上,你希望同时遍历多个列表,对此,zip非常有用。

import csv

fieldnames = []
val_lists = []
for d in data_set:
    # Find the only used key.
    # This is a bit awkward because of the initial data structure.
    k = d.keys()[0]
    fieldnames.append(k)
    val_lists.append(d[k])

with open('names.csv', 'w') as csvfile:
    writer = csv.writer(csvfile)    
    writer.writerow(fieldnames)

    for row in zip(*val_lists):
        # This picks one item from each list and builds a list.
        # The first row will be [0.98, 3.104]
        # The second row will be [0.97, 3.102]
        # ...
        writer.writerow(row)

请注意,当您使用zip时,无需使用DictWriter,因为这意味着您需要重新构建一个字典,而实际上并没有任何好处。

您也可以像@MartinEvans建议的那样更简洁地使用writerows(zip(*val_lists))来完成最后一部分。 - Bruno

2

这段代码可以帮助你,而不会被绑定在 data_set 中的某个特定字典数量上

我已经添加了另一个带有“Losses”键的字典进行测试

import csv

data_set = [
    {'Active rate': [0.98, 0.97, 0.96]},
    {'Operating Expense': [3.104, 3.102, 3.101]},
    {'Losses': [1.14, 2.28, 3.42]}
]

headers = [d.keys()[0] for d in data_set]

with open('names.csv', 'w') as csvfile:
    writer = csv.DictWriter(csvfile, fieldnames=headers)
    writer.writeheader()
    for item in zip(*[x.values()[0] for x in data_set]):
        more_results = list()
        more_results.append(headers)
        more_results.append(item)
        writer.writerow(dict(zip(*more_results)))

输出:

在此输入图片描述


(Note: 该文中的html标签已保留)

1
“这段代码将帮助您而不会被数据集中的某些字典所限制。”:我认为大多数其他答案已经考虑到了这一点。 - Bruno
@AndrésPérez-AlbelaH,对不起,我当然没有意味着抄袭,只是说那个特定点(data_set中的其他字典)已经在其他答案中处理过了。你的答案与其他人主要的区别在于它仍然使用了DictWriter。我不确定重建一个字典并使用DictWriter值得这么麻烦,这似乎更费事。 - Bruno
@PyAn 好的,让我看看。 - Andrés Pérez-Albela H.
1
@Bruno也许你可以帮我修改我的答案,而不是鼓励他不选择我的答案。 - Andrés Pérez-Albela H.
为了澄清我所说的小点,你可以这样做得更短(而且不需要重建字典):writer = csv.writer(csvfile); writer.writerow(headers); writer.writerows(zip(*[x.values()[0] for x in data_set]))。创建 more_results,然后用 dict(zip(*more_results)) 将其转换为字典,这只是因为使用了 DictWriter 才需要,似乎很复杂,可以通过一开始就使用普通的 writer 来避免。这就是我想说的。 - Bruno
显示剩余5条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接