सीएसवी फ़ाइल से एक शब्दकोश बनाना?


153

मैं एक csv फ़ाइल से एक शब्दकोश बनाने की कोशिश कर रहा हूँ। सीएसवी फ़ाइल के पहले कॉलम में अद्वितीय कुंजियाँ होती हैं और दूसरे कॉलम में मान होते हैं। सीएसवी फ़ाइल की प्रत्येक पंक्ति शब्दकोश के भीतर एक अद्वितीय कुंजी, मूल्य जोड़ी का प्रतिनिधित्व करती है। मैंने csv.DictReaderऔर 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
क्या आप एक इनपुट फ़ाइल और परिणामी डेटा संरचना का एक उदाहरण दे सकते हैं?
रॉबर्ट

1
जब आप csv.reader पर पुनरावृति करते हैं, तो आपको एकल पंक्ति मिलती है, न कि पंक्तियाँ। तो, वैध रूप mydict = {k: v for k, v in रीडर} है, लेकिन यदि आप सुनिश्चित हैं, कि csv फ़ाइल में केवल दो कॉलम हैं, तो mydict = तानाशाही (रीडर) बहुत तेज है।
एलेक्स लस्किन

जवाबों:


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
और फिर वह कम से कम अपवाद को दोषपूर्ण इनपुट के लिए कम करने में सक्षम हो जाएगा
मशीन

यह कुछ योग्यता है, लेकिन मैं एक दृढ़ विश्वास रखता हूं कि अपवाद आपको बताने के लिए हैं कि आपने कुछ गलत तरीके से प्रोग्राम किया है - न कि उस समय के लिए जब दुनिया आपको नींबू देती है। जब आप एक सुंदर त्रुटि संदेश प्रिंट करते हैं और विफल होते हैं, या - इस मामले के लिए अधिक उपयुक्त होते हैं - एक सुंदर चेतावनी संदेश और सफल होता है।
नैट

क्षमा करें, op के कोड को देखा, यह बताना मुश्किल है कि क्या वह प्रति पंक्ति केवल 2 आइटम चाहता था। मैं गलत था!
मशीन तड़पते हुए

1
सीएसवी में मेरी कई लाइनें थीं, लेकिन इसने केवल 1 कुंजी दी: वैल्यू पेयर
अभिलाष मिश्रा

80

फ़ाइल को खुला और फिर कॉल करके खोलें csv.DictReader

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

आप input_file पर पुनरावृत्ति करके csv फ़ाइल के तानाशाह रीडर ऑब्जेक्ट की पंक्तियों पर पुनरावृति कर सकते हैं।

for row in input_file:
    print(row)

या केवल पहली पंक्ति तक पहुँचने के लिए

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

अद्यतन अजगर 3+ संस्करणों में, यह कोड थोड़ा बदल जाएगा:

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

3
यह डिक्ट्रीडर ऑब्जेक्ट को डिक्शनरी नहीं बनाता है (और हां एक महत्वपूर्ण मूल्य जोड़ी नहीं)
एचएन सिंह

1
@ एच.एन. सिंह - हाँ, मुझे पता है - इरादा कुछ और ही मदद करेगा
लक्ष्मीकांत रत्नापर्खी

1
'डिक्ट्रीडर' ऑब्जेक्ट की कोई विशेषता नहीं है 'अगला'
पलक

1
@ पालक - यह पायथन 2.7 के लिए उत्तर दिया गया था, अजगर 3+ संस्करणों के next(dictobj)बजाय प्रयास करें dictobj.next()
लक्ष्मीकांत रत्नापारखी

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

6
अत्यधिक गैर-पाइथोनिक शैली।
एलेक्स लस्किन

47
@ अलेक्स लास्किन: वाक़ई? यह मेरे लिए कुछ सुंदर पठनीय लगता है। इस कथन को वापस करने के लिए आपका सिद्धांत क्या है? आपने मूल रूप से उसे "पॉपी हेड" कहा था ...
मशीन

26
@ मशीन-तड़प, नहीं, मैंने यह नहीं कहा कि उसका कोड 'खराब' है। लेकिन लिखने का कोई एक कारण नहीं है for row in reader: k, v = rowयदि आप बस for k, v in readerउदाहरण के लिए लिख सकते हैं । और अगर आप उम्मीद करते हैं, कि पाठक एक पुनरावृत्त है, दो-तत्व आइटम का उत्पादन कर रहा है, तो आप इसे सीधे रूपांतरण के लिए निर्धारित कर सकते हैं। d = dict(reader)विशाल डेटासेट पर बहुत छोटा और काफी तेज है।
एलेक्स लास्किन

44
@ एलेक्स लस्किन: स्पष्टीकरण के लिए धन्यवाद। मैं व्यक्तिगत रूप से आपके साथ सहमत हूं, लेकिन मुझे लगता है कि यदि आप किसी के कोड को "नॉन-पाइथोनिक" कहने जा रहे हैं, तो आपको उस टिप्पणी को उचित ठहराना चाहिए। मैं कहूंगा कि "छोटे" और "तेज" जरूरी "अधिक पायथोनिक" के बराबर नहीं हैं। पठनीयता / विश्वसनीयता एक बहुत बड़ी चिंता है। यदि यह हमारे कुछ बाधाओं में उपरोक्त 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
मेरी किताब में यह सबसे अच्छा जवाब है
बोर्ड्टक

और अगर हेडर है तो ...?
ndtreviv

@ndtreviv आप हेडर की अनदेखी के लिए स्किप्ट्रो का उपयोग कर सकते हैं।
मुदस्सिरखान

17

आपको बस csv.reader को तानाशाही में बदलना है:

~ >> 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
वह समाधान सुव्यवस्थित है, और महान काम करेगा यदि वह सुनिश्चित कर सकता है कि उसके इनपुट में कभी किसी पंक्ति में तीन या अधिक कॉलम नहीं होंगे। हालांकि, अगर वह कभी भी सामना किया जाता है, तो कुछ हद तक एक अपवाद इस तरह उठाया जाएगा ValueError: dictionary update sequence element #2 has length 3; 2 is required:।
नैट

@machine, प्रश्न में त्रुटि से देखते हुए, csv फ़ाइल में 2 से अधिक कॉलम हैं
John La Rooy

@gnibbler, नहीं, प्रश्न में त्रुटि पंक्ति के डबल अनपैकिंग के कारण है। पहले वह पाठक पर पुनरावृति करने की कोशिश करता है, पंक्तियों को प्राप्त करता है जो वास्तव में एकल पंक्ति है । और जब वह इस एकल पंक्ति पर पुनरावृति करने की कोशिश करता है, तो उसे दो आइटम मिलते हैं, जिन्हें सही ढंग से अनपैक नहीं किया जा सकता है।
एलेक्स लस्किन

एक सामान्य टिप्पणी: पुनरावृत्तियों से स्मृति में रखी गई वस्तुओं को बनाने से स्मृति समस्या हो सकती है। अपनी स्मृति स्थान और चलने योग्य स्रोत फ़ाइल के आकार की जाँच करने का सुझाव दें। पुनरावृत्तियों का एक मुख्य लाभ (संपूर्ण बिंदु) स्मृति में बड़ी चीजों को नहीं रखना है।
travelingbones

@ नैट: यदि filterकॉल के साथ लपेटकर आवश्यक हो map(operator.itemgetter(slice(2)), ...)तो इसे ठीक किया जा सकता है , इसलिए यह केवल पहले दो खुराकों को खींचेगा , जो इसे बनाएगा dict(map(operator.itemgetter(slice(2)), filter(None, csv.reader(f)))):। यदि यह पायथन 2 है, तो सुनिश्चित करें from future_builtins import map, filter, इसलिए dictकई अनावश्यक अस्थायी lists पहले उत्पादन के बजाय सीधे एक जनरेटर को पढ़ता है )।
शैडो रेंजर

12

इसके लिए आप खसखस ​​का भी इस्तेमाल कर सकते हैं।

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)

अच्छी तरह से किया और अच्छी तरह से सोचा दोनों। लेकिन जैसा कि मैंने ऊपर कहा था, क्या उन्हें वास्तव में इस तथ्य की अनदेखी करनी चाहिए कि उनकी इनपुट लाइन उनकी अपेक्षा से अधिक लंबी है? मैं कहूंगा कि अगर वह दो से अधिक वस्तुओं के साथ एक लाइन प्राप्त करता है, तो उसे अपना अपवाद (एक कस्टम संदेश के साथ) उठाना चाहिए।
मशीन तड़पते हुए

या बल्कि, जैसा कि ऊपर कहा गया है @ नोट, कम से कम एक चेतावनी संदेश मुद्रित करें। यह सिर्फ ऐसा प्रतीत नहीं होता है कि आप कुछ अनदेखा करना चाहते हैं।
मशीन तड़पते हुए

आपके उत्तर (बनाम मेरा) ने कुछ विचार किया - क्या इस मामले में स्लाइसिंग और इंडेक्सिंग के बीच दक्षता अंतर है?
नैट

1
@ माचिन, कोई विचार नहीं। शायद यह एक डेटाबेस से एक उपयोगकर्ता तालिका का एक डंप है, और वह बस उपयोगकर्ता का एक तानाशाही चाहता है: उपयोगकर्ता नाम या उदाहरण के लिए कुछ
जॉन ला रोय

1
हे दोस्तों, टिप्पणी के लिए धन्यवाद। आपकी चर्चा ने वास्तव में मेरी समस्या को हल करने में मदद की। अगर झंडा उम्मीद से ज्यादा लंबा है तो मुझे झंडा उठाने के बारे में विचार पसंद है। मेरा डेटा एक डेटाबेस डंप है और मेरे पास डेटा के दो से अधिक कॉलम हैं।
शराबी


3

यदि आप सुन्न पैकेज का उपयोग करने के साथ ठीक हैं, तो आप निम्न की तरह कुछ कर सकते हैं:

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

सरल सीएसवी फ़ाइलों के लिए, जैसे कि निम्नलिखित

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

नोट: पायथन शब्दकोशों में अद्वितीय कुंजियाँ हैं, इसलिए यदि आपकी सीएसवी फ़ाइल में डुप्लिकेट है 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_default: csv_dict.set_default (कुंजी, [])। परिशिष्ट ({कुंजी: मान के लिए मूल्य, ज़िप में मान (हेडर, मान)})
mdmjj

आपके .appendआदेश में ({key: value}) सिंटैक्स बहुत उपयोगी था। जब मैं एक सीएसवी फ़ाइल से बनाया गया था और उस वस्तु 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

कई समाधान पोस्ट किए गए हैं और मैं अपना योगदान देना चाहूंगा, जो सीएसवी फ़ाइल में विभिन्न कॉलमों के लिए काम करता है। यह प्रति स्तंभ एक कुंजी के साथ एक शब्दकोश बनाता है, और प्रत्येक कुंजी के लिए मूल्य ऐसे कॉलम में तत्वों के साथ एक सूची है।

    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

पांडा के साथ, यह बहुत आसान है, उदाहरण के लिए। यह मानते हुए कि आपके पास सीएसवी के रूप में निम्नलिखित डेटा है और इसे कॉल करते हैं test.txt/ test.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]}
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.