我正在尝试从csv文件创建字典。 csv文件的第一列包含唯一键,第二列包含值。 csv文件的每一行代表字典中的唯一键,值对。我尝试使用csv.DictReadercsv.DictWriter类,但是我只能弄清楚如何为每一行生成一个新字典。我要一部字典。这是我要使用的代码:

import csv

with open('coors.csv', mode='r') as infile:
    reader = csv.reader(infile)
    with open('coors_new.csv', mode='w') as outfile:
    writer = csv.writer(outfile)
    for rows in reader:
        k = rows[0]
        v = rows[1]
        mydict = {k:v for k, v in rows}
    print(mydict)


运行上述代码时,我得到的是ValueError: too many values to unpack (expected 2)。如何从csv文件创建一个字典?谢谢。

评论

您能举一个输入文件和结果数据结构的例子吗?

当您遍历csv.reader时,将得到单行,而不是行。因此,有效格式为mydict = {k:v for reader中的k,v},但是如果您确定csv文件中只有两列,则mydict = dict(reader)要快得多。

#1 楼

我相信您正在寻找的语法如下:

import csv

with open('coors.csv', mode='r') as infile:
    reader = csv.reader(infile)
    with open('coors_new.csv', mode='w') as outfile:
        writer = csv.writer(outfile)
        mydict = {rows[0]:rows[1] for rows in reader}


或者,对于python <= 2.7.1,您需要:

mydict = dict((rows[0],rows[1]) for rows in reader)


评论


占比预期更长的行很好;但是如果连续有太多项目,他不应该提出自己的例外吗?我认为那将意味着他的输入数据有错误。

–机器向往
2011年7月19日在1:22

然后他至少能够将异常范围缩小到错误输入

–机器向往
2011年7月19日在1:24

那有一些优点,但是我坚信,那里有例外可以告诉你,你对程序的编程不正确-不是因为世界给了你柠檬。那是当您打印出漂亮的错误消息并失败时,或者(对于这种情况更合适)打印出漂亮的警告消息并成功时。

–内特
2011年7月19日在1:25



抱歉,看了op的代码,很难说他是否只希望每行2个项目。我错了!

–机器向往
2011年7月19日在1:30



我在csv中有多行,但它只给出了1个key:value对

– Abhilash Mishra
19年7月31日在7:02

#2 楼

通过依次调用open和csv.DictReader来打开文件。

input_file = csv.DictReader(open("coors.csv"))


您可以通过遍历input_file来遍历csv文件dict阅读器对象的行。

for row in input_file:
    print(row)



仅访问第一行

dictobj = csv.DictReader(open('coors.csv')).next() 


UPDATE
在python 3+版本,此代码会稍有变化:

reader = csv.DictReader(open('coors.csv'))
dictobj = next(reader) 


评论


这使得DictReader对象不是字典(是的不是键值对)

– HN Singh
18年11月10日在17:52

@HN Singh-是的,我知道-意图是它也会帮助其他人

– Laxmikant Ratnaparkhi
18年11月14日在6:34

'DictReader'对象没有属性'next'

– Palak
19年5月28日在20:36

@Palak-Python 2.7已回答,请在Python 3+版本中尝试使用next(dictobj)而不是dictobj.next()。

– Laxmikant Ratnaparkhi
19年5月29日在21:52

#3 楼

import csv
reader = csv.reader(open('filename.csv', 'r'))
d = {}
for row in reader:
   k, v = row
   d[k] = v


评论


高度非Python风格。

– Alex Laskin
2011年7月19日,0:45

@Alex Laskin:真的吗?对我来说,它看起来像一些易读的python。您支持此声明的原则是什么?您基本上只是称他为“大便人头” ...

–机器向往
2011年7月19日,在1:17

@ machine-向往,不,我不是说他的代码很糟糕。但是,没有唯一的理由在阅读器中写行:k,v = row,例如,如果您可以简单地在阅读器中为k,v书写。而且,如果您期望该阅读器是可迭代的,可以生成两个元素的项目,则只需将其直接传递给字典即可进行转换。 d = dict(reader)在庞大的数据集上要短得多,并且要快得多。

– Alex Laskin
2011年7月19日在1:44



@Alex Laskin:感谢您的澄清。我个人同意您的看法,但我认为,如果您要称呼某人的代码为“非Python语言”,则应在说明中附上理由。我会说“更短”和“更快”不一定等同于“更pythonic”。可读性/可靠性也是一个很大的问题。如果在阅读器范式中将我们的某些约束纳入上面的工作范围以进行比较容易,那么它(在长期开发之后)可能更加实用。我短期内同意您的意见,但请提防过早的优化。

–机器向往
2011年7月19日,下午5:32

@robert:谢谢老兄!真的有帮助。其他代码太难读了。

–灰
10月22日17:13

#4 楼

这不是一个很好的解决方案,而是使用pandas的单行解决方案。

import pandas as pd
pd.read_csv('coors.csv', header=None, index_col=0, squeeze=True).to_dict()


如果要为索引指定dtype(如果您要在dtype中指定它,则不能在read_csv中指定由于存在错误,请使用index_col参数):

import pandas as pd
pd.read_csv('coors.csv', header=None, dtype={0: str}).set_index(0).squeeze().to_dict()


评论


在我的书中,这是最好的答案

–boardtc
19年4月12日在22:09

如果有标题...?

– ndtreviv
19年5月30日在9:59

@ndtreviv,您可以使用跳过行来忽略标题。

–mudassirkhan19
19年6月12日在7:30

#5 楼

您只需将csv.reader转换为dict:

~ >> cat > 1.csv
key1, value1
key2, value2
key2, value22
key3, value3

~ >> cat > d.py
import csv
with open('1.csv') as f:
    d = dict(filter(None, csv.reader(f)))

print(d)

~ >> python d.py
{'key3': ' value3', 'key2': ' value22', 'key1': ' value1'}


评论


该解决方案很整洁,并且如果他可以确定自己的输入在某行中永远不会有三列或更多列,那么它将非常有用。但是,如果遇到这种情况,将引发类似这样的异常:ValueError:字典更新序列元素#2的长度为3; 2是必需的。

–内特
2011年7月19日在1:17



@machine,从问题中的错误判断,csv文件有两列以上

– John La Rooy
2011年7月19日在1:22

@gnibbler,不,问题中的错误是由于行的两次解包所致。首先,他尝试遍历读取器,获得实际上是单行的行。当他尝试遍历这一行时,他得到了两个项目,无法正确解压。

– Alex Laskin
2011年7月19日在1:51

一个普遍的评论:使对象由可迭代对象保存在内存中会导致内存问题。建议检查您的内存空间和可迭代源文件的大小。可迭代对象的主要优点(要点是什么)不是在内存中保存大对象。

–旅行骨
16 Mar 4 '16 at 19:29

@Nate:可以在需要时通过将过滤器调用与map(operator.itemgetter(slice(2)),...)包装在一起来解决,因此它只会提取前两个迭代,从而使其成为:dict(map(operator .itemgetter(slice(2)),filter(None,csv.reader(f))))。如果使用的是Python 2,请确保从future_builtins导入映射,过滤器执行操作,以便dict直接读取生成器,而不是首先生成多个不必要的临时列表。

–ShadowRanger
16年6月8日在19:55

#6 楼

您也可以为此使用numpy。

from numpy import loadtxt
key_value = loadtxt("filename.csv", delimiter=",")
mydict = { k:v for k,v in key_value }


#7 楼

一线解决方案

import pandas as pd

dict = {row[0] : row[1] for _, row in pd.read_csv("file.csv").iterrows()}


#8 楼

我建议添加if rows,以防文件末尾出现空行

import csv
with open('coors.csv', mode='r') as infile:
    reader = csv.reader(infile)
    with open('coors_new.csv', mode='w') as outfile:
        writer = csv.writer(outfile)
        mydict = dict(row[:2] for row in reader if row)


评论


做得好和考虑周全。但是,就像我在上面说的那样,他是否真的应该忽略输入行比预期长的事实?我想说如果他得到一行包含两个以上项目的话,他应该提出自己的例外(带有自定义消息)。

–机器向往
2011年7月19日,在1:27

或者更确切地说,如上面@Nate所述,至少打印警告消息。这似乎并不是您想要忽略的东西。

–机器向往
2011年7月19日在1:29

您的回答(相对于我的回答)使您有所思考-在这种情况下,切片和索引编制之间是否存在效率差异?

–内特
2011年7月19日在1:29

@机器,不知道。也许这是数据库中用户表的转储,他只想要一个userid:username的字典,例如

– John La Rooy
2011年7月19日在1:30

大家好,感谢您的评论。您的讨论确实帮助我解决了我的问题。我喜欢关于如果输入时间长于预期的情况下升旗的想法。我的数据是数据库转储,确实有两列以上的数据。

– drbunsen
2011年7月19日在1:48

#9 楼

对于简单的csv文件,例如以下

id,col1,col2,col3
row1,r1c1,r1c2,r1c3
row2,r2c1,r2c2,r2c3
row3,r3c1,r3c2,r3c3
row4,r4c1,r4c2,r4c3


您可以仅使用内置插件将其转换为Python字典

with open(csv_file) as f:
    csv_list = [[val.strip() for val in r.split(",")] for r in f.readlines()]

(_, *header), *data = csv_list
csv_dict = {}
for row in data:
    key, *values = row   
    csv_dict[key] = {key: value for key, value in zip(header, values)}


这将产生以下字典

{'row1': {'col1': 'r1c1', 'col2': 'r1c2', 'col3': 'r1c3'},
 'row2': {'col1': 'r2c1', 'col2': 'r2c2', 'col3': 'r2c3'},
 'row3': {'col1': 'r3c1', 'col2': 'r3c2', 'col3': 'r3c3'},
 'row4': {'col1': 'r4c1', 'col2': 'r4c2', 'col3': 'r4c3'}}


注意:Python词典具有唯一键,因此,如果您的csv文件具有重复的ids,则应添加每行到列表。

for row in data:
    key, *values = row

    if key not in csv_dict:
            csv_dict[key] = []

    csv_dict[key].append({key: value for key, value in zip(header, values)})


评论


n.b.可以全部缩短为使用set_default:csv_dict.set_default(key,[])。append({key:key的值,zip中的值(header,values)}))

–mdmjsh
19年11月29日在13:46

.append命令中的({key:value})语法非常有用。在遍历并添加到由CSV文件制成的DictReader对象时,最终在row.update中使用了相同的语法。

–Shrout1
6月12日12:53

#10 楼

如果可以使用numpy包,则可以执行以下操作:

import numpy as np

lines = np.genfromtxt("coors.csv", delimiter=",", dtype=None)
my_dict = dict()
for i in range(len(lines)):
   my_dict[lines[i][0]] = lines[i][1]


#11 楼

您可以使用它,它非常酷:

import dataconverters.commas as commas
filename = 'test.csv'
with open(filename) as f:
      records, metadata = commas.parse(f)
      for row in records:
            print 'this is row in dictionary:'+rowenter code here


#12 楼

假设您具有以下结构的CSV:
"a","b"
1,2
3,4
5,6

,并且您希望输出为:
[{'a': '1', ' "b"': '2'}, {'a': '3', ' "b"': '4'}, {'a': '5', ' "b"': '6'}]

zip函数(尚未提及)非常简单并且非常有用。 br />
def read_csv(filename):
    with open(filename) as f:
        file_data=csv.reader(f)
        headers=next(file_data)
        return [dict(zip(headers,i)) for i in file_data]


#13 楼

已发布了许多解决方案,我想为我的做出贡献,该解决方案适用于CSV文件中不同数量的列。
它创建一个字典,每列一个键,每个键的值是列出该列中的元素。

    input_file = csv.DictReader(open(path_to_csv_file))
    csv_dict = {elem: [] for elem in input_file.fieldnames}
    for row in input_file:
        for key in csv_dict.keys():
            csv_dict[key].append(row[key])


#14 楼

例如,使用大熊猫会更容易。
假设您具有以下数据作为CSV并将其称为test.txt / test.csv(您知道CSV是一种文本文件)

a,b,c,d
1,2,3,4
5,6,7,8


现在使用熊猫

import pandas as pd
df = pd.read_csv("./text.txt")
df_to_doct = df.to_dict()

每行将是

df.to_dict(orient='records')


/>就这样。

#15 楼

尝试使用defaultdictDictReader

import csv
from collections import defaultdict
my_dict = defaultdict(list)

with open('filename.csv', 'r') as csv_file:
    csv_reader = csv.DictReader(csv_file)
    for line in csv_reader:
        for key, value in line.items():
            my_dict[key].append(value)


它返回:

{'key1':[value_1, value_2, value_3], 'key2': [value_a, value_b, value_c], 'Key3':[value_x, Value_y, Value_z]}


#16 楼

如果您有:

csv中的值只有1个键和1个值作为键,
不想导入其他包
想一次创建一个字典

/>
执行此操作:
 mydict = {y[0]: y[1] for y in [x.split(",") for x in open('file.csv').read().split('\n') if x]}
 

它是做什么的?
它使用列表推导拆分行和最后一个“ if x”用于忽略空行(通常在末尾),然后使用字典理解将其解包为字典。