如何将这个字典列表转换为CSV文件?

265

我有一个字典列表,看起来像这样:

toCSV = [{'name':'bob','age':25,'weight':200},{'name':'jim','age':31,'weight':180}]

我该怎么做才能将它转换为类似于这样的 csv 文件:

name,age,weight
bob,25,200
jim,31,180

可能是使用DictWriter在Python中编写CSV文件头的重复问题。 - SilentGhost
8个回答

465
import csv

to_csv = [
    {'name': 'bob', 'age': 25, 'weight': 200},
    {'name': 'jim', 'age': 31, 'weight': 180},
]

keys = to_csv[0].keys()

with open('people.csv', 'w', newline='') as output_file:
    dict_writer = csv.DictWriter(output_file, keys)
    dict_writer.writeheader()
    dict_writer.writerows(to_csv)

当数据被嵌入时,有没有一种方法可以做到这一点?例如,如果每个数组条目都是{{"first":"John", "last": "Doe"}, uri},但您希望CSV仅包含名字和姓氏的数据。 - John
如果我的字典值中包含西里尔字母,我该如何将这样的文件写入CSV格式?我尝试使用.encode('utf-8'),但不幸的是,在CSV文件中,这些值并没有正确显示。 - BiXiC
24
如果第一个列表项不包含所有键,则无法工作。 - greg121
16
使用set().union(*(d.keys() for d in mylist))可以获取列表中的所有键(即使有些字典中没有所有的键)。 - Julian Camilleri
@Astarno 是的,这是正常的。CSV文件只是一个文本文件。您可能正在使用“表格计算工具”查看您的CSV。您必须将数据从CSV导入您的软件/工具中(同时指定分隔符和引用字符),以便能够查看不同的列。 - stackprotector
显示剩余2条评论

37

在Python 3中,有些事情略有不同,但更简单且容错性较低。最好告诉CSV文件应使用utf8编码打开,因为这样可以使数据更便携(假设您没有使用更严格的编码,比如latin1)。

import csv
toCSV = [{'name':'bob','age':25,'weight':200},
         {'name':'jim','age':31,'weight':180}]
with open('people.csv', 'w', encoding='utf8', newline='') as output_file:
    fc = csv.DictWriter(output_file, 
                        fieldnames=toCSV[0].keys(),

                       )
    fc.writeheader()
    fc.writerows(toCSV)
  • 请注意,在Python 3中使用csv需要添加newline=''参数,否则在Excel或OpenCalc中打开CSV文件时会出现空行。

另外,我更喜欢使用pandas模块中的CSV处理程序。我发现它对编码问题更加宽容,当加载文件时,pandas会自动将CSV中的字符串数字转换为正确的类型(int、float等)。

import pandas
dataframe = pandas.read_csv(filepath)
list_of_dictionaries = dataframe.to_dict('records')
dataframe.to_csv(filepath)

注意:

  • 如果您提供路径,则pandas将为您打开文件,并在python3中默认使用utf8,并找出标题。
  • 数据帧与CSV给出的结构不同,因此加载时需要添加一行以获得相同的东西:dataframe.to_dict('records')
  • pandas还可以更轻松地控制csv文件中列的顺序。默认情况下,它们是按字母顺序排列的,但是您可以指定列顺序。使用vanilla csv模块需要提供一个OrderedDict,否则它们将以随机顺序出现(如果在python < 3.5中工作)。有关详细信息,请参见:Preserving column order in Python Pandas DataFrame

3
如何将字典列表写入CSV文件?我看不懂第二个代码示例。 - Iain Samuel McLean Elder
@IainSamuelMcLeanElder .to_dict 返回数据框的多种格式之一,具体取决于您指定的内容。('records') 返回一个字典列表,其中每个列都是一个字典,而 .to_dict('index') 返回一个字典,其中顶层键是索引值,嵌套字典是 column:value 对。根据您导出 CSV 的方式,选择 CSV 函数所需的结构。 - Marc Maxmeister
5
您的第二个代码示例似乎没有回答提问者的问题。它不应该在某处使用from_dict吗?我曾经遇到同样的问题,这是对我的有效解决方法。了解to_dict很好,但它似乎更适用于读取,而不是写入。 - Iain Samuel McLean Elder

19

这是当您有一个字典列表时的情况:

import csv
with open('names.csv', 'w') as csvfile:
    fieldnames = ['first_name', 'last_name']
    writer = csv.DictWriter(csvfile, fieldnames=fieldnames)
    writer.writeheader()
    writer.writerow({'first_name': 'Baked', 'last_name': 'Beans'})

9

因为@User和@BiXiC在这里寻求UTF-8的帮助,所以这里提供了@Matthew的解决方案的变体。(我不能评论,所以我回答。)

import unicodecsv as csv
toCSV = [{'name':'bob','age':25,'weight':200},
         {'name':'jim','age':31,'weight':180}]
keys = toCSV[0].keys()
with open('people.csv', 'wb') as output_file:
    dict_writer = csv.DictWriter(output_file, keys)
    dict_writer.writeheader()
    dict_writer.writerows(toCSV)

7

使用Pandas的简短解决方案

import pandas as pd

list_of_dicts = [
    {'name': 'bob', 'age': 25, 'weight': 200},
    {'name': 'jim', 'age': 31, 'weight': 180},
]

df = pd.DataFrame(list_of_dicts) 
df.to_csv("names.csv", index=False)

2
import csv

with open('file_name.csv', 'w') as csv_file:
    writer = csv.writer(csv_file)
    writer.writerow(('colum1', 'colum2', 'colum3'))
    for key, value in dictionary.items():
        writer.writerow([key, value[0], value[1]])

这是向.csv文件写入数据的最简单方式。

2

这里有另一种更通用的解决方案,假设您没有行列表(也许它们不适合内存)或标题的副本(也许write_csv函数是通用的):

def gen_rows():
    yield OrderedDict(name='bob', age=25, weight=200)
    yield OrderedDict(name='jim', age=31, weight=180)

def write_csv():
    it = genrows()
    first_row = it.next()  # __next__ in py3
    with open("people.csv", "w") as outfile:
        wr = csv.DictWriter(outfile, fieldnames=list(first_row))
        wr.writeheader()
        wr.writerow(first_row)
        wr.writerows(it)

注意: 这里使用的OrderedDict构造函数只在python>3.4中保留顺序。 如果顺序很重要,请使用OrderedDict([('name','bob'),('age',25)])形式。


1
以前从没见过有人在生成器中存储数据 - 这是一种有趣的方法。 - Marc Maxmeister

1
import csv
toCSV = [{'name':'bob','age':25,'weight':200},
         {'name':'jim','age':31,'weight':180}]
header=['name','age','weight']     
try:
   with open('output'+str(date.today())+'.csv',mode='w',encoding='utf8',newline='') as output_to_csv:
       dict_csv_writer = csv.DictWriter(output_to_csv, fieldnames=header,dialect='excel')
       dict_csv_writer.writeheader()
       dict_csv_writer.writerows(toCSV)
   print('\nData exported to csv succesfully and sample data')
except IOError as io:
    print('\n',io)

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