2009-05-05 8 views
8

तो मैं दो .csv फ़ाइलें है जहां फ़ाइल 1 में पहली पंक्ति है:आम कॉलम के आधार पर 2 .csv फ़ाइलें संयोजन

MPID,Title,Description,Model,Category ID,Category Description,Subcategory ID,Subcategory Description,Manufacturer ID,Manufacturer Description,URL,Manufacturer (Brand) URL,Image URL,AR Price,Price,Ship Price,Stock,Condition 

फ़ाइल 2 से पहली पंक्ति:

Regular Price,Sale Price,Manufacturer Name,Model Number,Retailer Category,Buy URL,Product Name,Availability,Shipping Cost,Condition,MPID,Image URL,UPC,Description 

और उसके बाद बाकी की हर जानकारी जानकारी से भरा है।

जैसा कि आप देख सकते हैं, दोनों फाइलों में एमपीआईडी ​​(फ़ाइल 1: कॉल 1, फ़ाइल 2: कॉल 9 नामक एक सामान्य क्षेत्र है, जहां पहला कॉल कोल 1 है)।

मैं एक नई फाइल बनाना चाहता हूं जो इस कॉलम को देखकर इन दो फाइलों को जोड़ देगा (जैसा कि: यदि दोनों फाइलों में एक एमपीआईडी ​​है, तो नई फाइल में यह एमपीआईडी ​​इसके दोनों के साथ दिखाई देगा फ़ाइल 1 से पंक्ति और फ़ाइल 2 से इसकी पंक्ति)। यदि एक एमपीआईडी ​​केवल एक फ़ाइल में दिखाई देता है तो इसे भी इस संयुक्त फाइल में जाना चाहिए।

फ़ाइलों को किसी भी तरह से क्रमबद्ध नहीं किया गया है।

मैं इसे डेबियन मशीन पर शैल स्क्रिप्ट या पायथन के साथ कैसे कर सकता हूं?

धन्यवाद।

संपादित करें: दोनों फाइलों में फ़ील्ड को अलग करने वाले लोगों के अलावा अल्पविराम नहीं है।

उत्तर

0

ऐसा लगता है कि आप एक शेल स्क्रिप्ट में करने की कोशिश कर रहे हैं, जो आमतौर पर SQL सर्वर का उपयोग करके किया जाता है। क्या उस कार्य के लिए एसक्यूएल का उपयोग करना संभव है? उदाहरण के लिए, आप दोनों फाइलों को mysql में आयात कर सकते हैं, फिर एक जॉइन बनाएं, फिर इसे CSV पर निर्यात करें।

1

आपको खोल में join कमांड को देखने की आवश्यकता होगी। आपको डेटा को सॉर्ट करने की भी आवश्यकता होगी, और शायद पहली पंक्तियां खो देंगी। यदि किसी भी डेटा में अल्पविराम शामिल है तो पूरी प्रक्रिया फ्लैट गिर जाएगी। या आपको एक CSV- संवेदनशील प्रक्रिया के साथ डेटा को संसाधित करने की आवश्यकता होगी जो एक अलग फ़ील्ड विभाजक (शायद नियंत्रण-ए) पेश करता है जिसका उपयोग आप अनजाने में फ़ील्ड को विभाजित करने के लिए कर सकते हैं।

पाइथन का उपयोग करने वाला विकल्प, दो फाइलों को शब्दकोशों की एक जोड़ी (सामान्य कॉलम पर कुंजी) में पढ़ता है और फिर दो शब्दकोशों के छोटे से सभी तत्वों को कवर करने के लिए लूप का उपयोग करता है, मिलान करने के लिए देखता है दूसरे में मूल्य। (यह मूल नेस्टेड लूप क्वेरी प्रोसेसिंग है।)

+1

काम करता है महान में शामिल होने के; लेकिन इनपुट फ़ाइलों को कुंजी पर क्रमबद्ध किया जाना चाहिए। यह मनमाने ढंग से सीएसवी फाइलों को भी पढ़ नहीं सकता है। विशेष रूप से, एक उद्धृत क्षेत्र के भीतर एक अल्पविराम उस रिकॉर्ड के लिए सभी फ़ील्डमों को स्थानांतरित करेगा – Javier

+0

@ जेवियर: सहमत - यही कारण है कि मैंने आपकी टिप्पणी को बिना देखे, यहां तक ​​कि मैंने आपकी टिप्पणी को देखे बिना भी जवाब दिया (जो शायद उसी समय तैयारी में था संपादन)। –

13
sort -t , -k index1 file1 > sorted1 
sort -t , -k index2 file2 > sorted2 
join -t , -1 index1 -2 index2 -a 1 -a 2 sorted1 sorted2 
+6

उद्धृत अल्पविराम से सावधान रहें! किसी भी उद्धरण का पालन न करें और न ही किसी उद्धरण का पालन करें – Javier

9

यह शास्त्रीय "संबंधपरक शामिल" समस्या है।

आपके पास कई एल्गोरिदम हैं।

  • नेस्टेड लूप्स। आप "मास्टर" रिकॉर्ड चुनने के लिए एक फ़ाइल से पढ़ते हैं। आप मास्टर से मेल खाने वाले सभी "विवरण" रिकॉर्ड्स को ढूंढने वाली पूरी दूसरी फ़ाइल पढ़ते हैं। यह विचार अच्छा नहीं है।

  • सॉर्ट-मर्ज करें। आप सामान्य फ़ाइल के आधार पर प्रत्येक फ़ाइल को एक अस्थायी प्रति में सॉर्ट करते हैं। फिर आप मास्टर से पढ़कर और फिर सभी मिलान पंक्तियों को विस्तार से पढ़कर और विलय किए गए रिकॉर्ड लिखकर दोनों फ़ाइलों को मर्ज करें।

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

इनमें से, सॉर्ट-विलय अक्सर सबसे तेज़ होता है। यह पूरी तरह से यूनिक्स sort कमांड का उपयोग कर किया जाता है।

लुक कार्यान्वयन

import csv 
import collections 

index = collections.defaultdict(list) 

file1= open("someFile", "rb") 
rdr= csv.DictReader(file1) 
for row in rdr: 
    index[row['MPID']].append(row) 
file1.close() 

file2= open("anotherFile", "rb") 
rdr= csv.DictReader(file2) 
for row in rdr: 
    print row, index[row['MPID']] 
file2.close() 
+0

पाइथन 2.2 के बाद से, मेरा मानना ​​है कि डिक्ट्रेडर __getitem__ लागू नहीं करता है। यह गति कारणों से किया गया था। तो कोड: index[rdr['MPID']].append(row) एट्रिब्यूट एरर के साथ असफल हो जाएगा: डिक्ट्रिडर उदाहरण में कोई विशेषता नहीं है '__getitem__' – uman

+0

@uman: डिक्ट्रेडर का परिणाम प्रथम श्रेणी की 'dict' ऑब्जेक्ट है। सभी 'dict' विधियों के साथ बरकरार है। –

+0

@ एसएलॉट: शायद आपका कोड गलत था। मैं पाइथन के साथ बहुत जंगली हूं, लेकिन एट्रिब्यूट एरर में आपके कोड परिणामों के साथ एमपीआईडी ​​के उदाहरण की कोशिश कर रहा हूं। देखें: http://pastebin.com/VJgSfA3u पीएस किसी को भी टिप्पणियों में स्वरूपण को एम्बेड करने के बारे में पता है? – uman

0

तुम मेरे FOSS परियोजना CSVfix, जो CSV फ़ाइलों जोड़ तोड़ के लिए एक धारा संपादक है पर एक नज़र ले सकता है। यह इसके अन्य विशेषताओं के बीच जुड़ने का समर्थन करता है, और उपयोग करने के लिए कोई स्क्रिप्टिंग की आवश्यकता नहीं है।

0

एक या अधिक सामान्य कॉलम के आधार पर एकाधिक फ़ाइलों (यहां तक ​​कि 2) विलय करने के लिए, अजगर में सबसे अच्छे और कुशल दृष्टिकोणों में से एक "ब्रूवरी" का उपयोग करना होगा। आप यह भी निर्दिष्ट कर सकते हैं कि विलय के लिए किन क्षेत्रों पर विचार किया जाना चाहिए और किन क्षेत्रों को सहेजने की आवश्यकता है।

import brewery 
from brewery 
import ds 
import sys 

sources = [ 
    {"file": "grants_2008.csv", 
    "fields": ["receiver", "amount", "date"]}, 
    {"file": "grants_2009.csv", 
    "fields": ["id", "receiver", "amount", "contract_number", "date"]}, 
    {"file": "grants_2010.csv", 
    "fields": ["receiver", "subject", "requested_amount", "amount", "date"]} 
] 

सभी क्षेत्रों की सूची बनाएं और डेटा की उत्पत्ति के बारे में जानकारी स्टोर करने के लिए फ़ाइल नाम जोड़ने के स्रोत परिभाषाओं के माध्यम से records.Go और खेतों इकट्ठा:

for source in sources: 
    for field in source["fields"]: 
     if field not in all_fields: 

out = ds.CSVDataTarget("merged.csv") 
out.fields = brewery.FieldList(all_fields) 
out.initialize() 

for source in sources: 

    path = source["file"] 

# Initialize data source: skip reading of headers 
# use XLSDataSource for XLS files 
# We ignore the fields in the header, because we have set-up fields 
# previously. We need to skip the header row. 

    src = ds.CSVDataSource(path,read_header=False,skip_rows=1) 

    src.fields = ds.FieldList(source["fields"]) 

    src.initialize() 


    for record in src.records(): 

    # Add file reference into ouput - to know where the row comes from 
    record["file"] = path 

     out.append(record) 

# Close the source stream 

    src.finalize() 


cat merged.csv | brewery pipe pretty_printer 
संबंधित मुद्दे