CSV 파일에서 사전을 작성 하시겠습니까?


153

CSV 파일에서 사전을 만들려고합니다. csv 파일의 첫 번째 열은 고유 키를 포함하고 두 번째 열은 값을 포함합니다. csv 파일의 각 행은 사전 내의 고유 키, 값 쌍을 나타냅니다. csv.DictReaderand csv.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 파일에서 하나의 사전을 작성하는 방법 감사.


2
입력 파일 및 결과 데이터 구조의 예를 제공 할 수 있습니까?
robert

1
csv.reader를 반복하면 행이 아닌 단일 행이 생성됩니다. 따라서 유효한 형식은 mydict = {리더에서 k, v의 경우 k : v}입니다. 확실하다면 csv 파일에 두 개의 열만 있으면 mydict = dict (reader)가 훨씬 빠릅니다.
Alex Laskin

답변:


155

찾고있는 구문은 다음과 같습니다.

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}

또는 파이썬 <= 2.7.1의 경우 다음을 원합니다.

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

2
예상보다 긴 행을 설명하는 것이 좋습니다. 그러나 너무 많은 아이템이 연속으로 있다면 그는 자신의 예외를 제기해서는 안됩니까? 입력 데이터에 오류가 있음을 의미한다고 생각합니다.
열망 기계

1
그리고 그는 적어도 잘못된 입력 예외를 좁힐 수있을 것입니다
기계 동경

그것은 약간의 장점이 있지만, 세상이 당신에게 레몬을 줄 때가 아닌 무언가를 잘못 프로그래밍했다는 것을 알려주는 예외가 있다고 확고한 신자입니다. 그것은 당신이 예쁜 오류 메시지를 인쇄하고 실패했을 때, 또는이 경우에 더 적합하면 예쁜 경고 메시지이며 성공합니다.
Nate

죄송합니다. op의 코드를 살펴 보니 한 줄에 2 개의 항목 만 원했는지 알기가 어렵습니다. 내가 틀렸어!
기계 갈망

1
나는 CSV에서 여러 줄을했지만, 그것은 단지 1 키를 주었다 값 쌍
Abhilash 슈라에게

80

open을 호출하여 파일을 엽니 다 csv.DictReader.

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

input_file을 반복하여 csv 파일 dict reader 오브젝트의 행을 반복 할 수 있습니다.

for row in input_file:
    print(row)

또는 첫 줄에만 액세스

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

UPDATE 파이썬 3+ 버전에서,이 코드는 조금 변경합니다 :

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

3
이렇게하면 DictReader 개체가 사전이 아니며 키 값 쌍이 아닙니다.
HN Singh

1
@HN Singh-예, 알고 있습니다. 의도는 다른 사람에게도 도움이 될 것입니다.
Laxmikant Ratnaparkhi

1
'DictReader'객체에는 'next'속성이 없습니다
Palak

1
@Palak-Python 2.7에 대한 답변이되었으므로 Python 3 이상 버전 next(dictobj)대신 사용해보십시오 dictobj.next().
Laxmikant Ratnaparkhi

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

6
비 파이썬 스타일.
Alex Laskin

47
@Alex Laskin : 정말요? 나에게 꽤 읽기 쉬운 파이썬처럼 보입니다. 이 진술을 뒷받침하는 원칙은 무엇입니까? 당신은 기본적으로 그냥 ... "바보 씨의 머리"그에게 전화
기계 동경

26
@ machine-yearning, 아니, 나는 그의 코드가 '나쁘다'고 말하지 않았다. 예를 들어 for row in reader: k, v = row간단히 쓸 수 있다면 글을 쓸 이유가 없습니다 for k, v in reader. 또한 독자가 반복 가능하고 요소가 2 개인 항목을 생성하는 것으로 예상되는 경우 변환을 지시하기 위해 직접 전달할 수 있습니다. d = dict(reader)거대한 데이터 세트에서 훨씬 짧고 훨씬 빠릅니다.
Alex Laskin

44
@Alex Laskin : 설명해 주셔서 감사합니다. 나는 개인적으로 당신과 동의했지만 당신이 누군가의 코드를 "비-음성"이라고 부르려면 그 의견을 정당화해야합니다. "짧게"와 "빠르게"가 반드시 "더 많은 pythonic"과 같은 것은 아닙니다. 가독성 / 신뢰성 역시 큰 관심사입니다. 위의 for row in reader패러다임 에 대한 일부 제약 조건에서 작업하기가 더 쉬운 경우 (장기 개발 후) 더 실용적 일 수 있습니다. 단기적으로는 동의하지만 조기 최적화에주의하십시오.
기계를 갈망하는 기계

30

이것은 우아하지는 않지만 팬더를 사용하는 한 줄 솔루션입니다.

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

인덱스에 dtype을 지정하려면 ( 버그 때문에 index_col 인수를 사용하는 경우 read_csv에 지정할 수 없습니다 ) :

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

3
내 책에서 이것은 가장 좋은 답변입니다
boardtc

그리고 헤더가 있다면 ...?
ndtreviv

@ndtreviv 헤더를 무시하기 위해 skiprows를 사용할 수 있습니다.
mudassirkhan19

17

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'}

5
이 솔루션은 깔끔하고 입력이 행에 3 개 이상의 열을 가지지 않을 것이라고 확신 할 수 있다면 훌륭하게 작동 합니다. 그러나 이것이 발생하면 다음과 같은 예외가 발생 ValueError: dictionary update sequence element #2 has length 3; 2 is required합니다.
Nate

@machine, 문제의 오류로 판단하면 csv 파일에 2 개 이상의 열이 있습니다
John La Rooy

@ gnibbler, 아니오, 질문의 오류는 두 번의 행 풀기 때문입니다. 먼저 그는 독자를 반복하여 실제로 단일 행 인 을 얻습니다 . 그리고이 단일 행을 반복하려고 할 때 올바르게 포장을 풀 수없는 두 개의 항목을 얻습니다.
Alex Laskin

일반적인 의견 : 반복 가능한 객체에서 메모리에 객체를 보관하면 메모리 문제가 발생할 수 있습니다. 메모리 공간과 반복 가능한 소스 파일의 크기를 확인하십시오. iterables의 주요 장점 (요점은?)은 큰 것을 메모리에 저장하지 않는 것입니다.
travelingbones

@Nate :으로 filter호출을 줄임으로써 필요한 경우 고칠 수 있으므로 map(operator.itemgetter(slice(2)), ...)처음 두 개의 iterms 만 가져 와서 만듭니다 dict(map(operator.itemgetter(slice(2)), filter(None, csv.reader(f)))). 파이썬 2 인 경우 반드시해야 from future_builtins import map, filter하므로 dict여러 개의 불필요한 임시를 list먼저 생성하는 대신 생성기를 직접 읽습니다 .
ShadowRanger 2016 년

12

이것을 위해 numpy를 사용할 수도 있습니다.

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

5

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)

잘하고 생각한 모두. 그러나 위에서 말했듯이 입력 라인이 예상보다 길다는 사실을 정말로 무시해야합니까? 두 개 이상의 품목이있는 행을 얻는 경우 (사용자 정의 메시지와 함께) 자신의 예외를 제기해야한다고 말하고 싶습니다.
기계 갈망

또는 @Nate가 위에서 언급 한 것처럼 적어도 경고 메시지를 인쇄하십시오. 이것은 단지 당신이 무시하고 싶은 것처럼 보이지 않습니다.
기계 갈망

당신의 대답 (내 대)은 무언가를 숙고했습니다.이 경우 슬라이싱과 인덱싱 사이에 효율성 차이가 있습니까?
Nate

1
@machine, 몰라요. 아마도 데이터베이스에서 사용자 테이블을 덤프 한 것일뿐입니다. 그는 userid : username 또는 그와 같은 단어를 원합니다.
John La Rooy

1
이봐, 댓글 주셔서 감사합니다. 당신의 토론은 정말 내 문제를 해결하는 데 도움이되었습니다. 입력이 예상보다 길면 플래그를 올리는 것에 대한 아이디어가 마음에 듭니다. 내 데이터는 데이터베이스 덤프이며 두 개 이상의 데이터 열이 있습니다.
drbunsen

5

원 라이너 솔루션

import pandas as pd

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

3

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]

3

다음과 같은 간단한 CSV 파일

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

내장 기능 만 사용하여 파이썬 사전으로 변환 할 수 있습니다

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)})

nb set_defaultcsv_dict.set_default (key, []). append ({key : 키 값, zip 값 (헤더, 값)}))
mdmjsh

명령의 ({key : value}) 구문 .append이 매우 유용했습니다. CSV 파일로 만든 객체를 row.update반복하고 추가 할 때 동일한 구문을 사용했습니다 DictReader.
Shrout1

1

이것을 사용할 수 있습니다.

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

1

많은 솔루션이 게시되었으며 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])

1

예를 들어 팬더를 사용하면 훨씬 쉽습니다. 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')

그리고 그게 다야.


0

defaultdict과 를 사용하십시오 DictReader.

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]}
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.