2012-02-28 12 views
2

私は、比較する必要があり、一致する他のファイル(5列)から行を抽出する必要がある2つのCSVファイル(3列)があります。ファイルのための例は以下のとおりです。CSVファイルから列のエントリを比較し、一致したPythonを抽出します

はFile1:

ATGCGCGACAGT, ch3, 123546 
ATGCATACAGGATAT, ch2, 5141561615 

......ように、約100エントリ

File2の:

ATGCGGCGACAGT,ch3, 123456,mi141515, AUCAGCUAUAUAU, UACGCAGAUAUAUA 
ATCAGACGATTATGA, ch4, 4564764, mi653453, AUCAGCAAUUUUCG, AUACAGACAAAAA 

....約上のように、 50000 entries

私はfile1の3つの列すべてが同じように両方のファイルの列1,2,3と一致する必要がありますfile2と一致する必要があります。このような場合は、さらに処理するために4,5および6列を抽出します。

私が考えていた:

fhout=csv.writer(open('parsed_out', 'w'), delimiter=',') 

for i in file1: 

    a=[0] 
    b=[1] 
    c=[2] 
     for x in file2: 
     d=[0] 
     e=[1] 
     f=[2] 
     g=[3] 
     h=[4] 
     i=[5] 
     if a==d and b==e and c==f: 
      fhout.writerow([g]+[h]+[i]) 
     else: 
      pass 

しかし、誰かが私より良い方法を提案してください、私はハッシュかというfile1の

で10,000以上のエントリのような大きなループを書いて、いくつかのより良い方法を使用することができることを教えてくれましたこれを達成する。ファイル1とファイル2の両方がより複雑なファイルから解析されます。

+1

いくつかのsqliteテーブルにデータをロードしてから、必要な列にそれらを結合することができます。 – imm

答えて

3

ような何か試してみてください:

file_1.csv

person, john, smith 
person, anne, frank 
person, bob, macdonald 
fruit, orange, banana 
fruit, strawberry, fields 
fruit, ringring, banana 

file_2.csv

:以下のデータを使用して実行すると

import csv 

file_1_tuples = [] 

with open("file_1.csv") as fh: 
    csv_reader = csv.reader (fh) 
    for row in csv_reader: 
     file_1_tuples.append( tuple(row) ) 

with open("file_2.csv") as fh: 
    csv_reader = csv.reader (fh) 
    for row in csv_reader: 
     if tuple(row[0:3]) in file_1_tuples: 
      print (row[3:6]) 

が出力

[' 1', ' 2', ' 3'] 
[' 4', ' 5', ' 6'] 
[' 7', ' 8', ' 9'] 

EDIT生成: Aわずかによりよい実装セットとリストの内包を使用して:

import csv, pprint 

with open("file_1.csv") as fh: 
    csv_reader = csv.reader (fh) 
    file_1_tuples = { tuple(row) for row in csv_reader } 

with open("file_2.csv") as fh: 
    csv_reader = csv.reader (fh) 
    matched_rows = [ row for row in csv_reader if (tuple(row[:3]) in file_1_tuples)] 

pprint.pprint (matched_rows) 

EDIT 2:この実装は空白に敏感であること注CSVファイル内のCSVファイル内のスペースが矛盾する場合は、row = [element.strip(' ') for element in row]のようなものを使用してすべてのスペースを取り除きます。

+0

なぜfile2のタプルがfile_1_tuplesと一致するように0-3から作られたのですか?それは0-2でなければならない?これはfile1のタプルと一致するファイル2の最初の3つの要素です。 – Bade

+0

@AtulKakrana:Pythonで配列をスライスする場合、開始インデックスはインクルードされていますが、* endインデックスは 'a = [10,20,30,40,50,60]'、 'a [0:2 ] '' [10,20] 'のみを与える。 'a [0:3]'または 'a [:3]'は最初の3つの要素 '[10,20,30]'を与えます。 –

2

ファイル1のフィールドをタプルに入れ、各タプルをセットに追加します。その後、セット上のファイル2の最初の3つのフィールドで封じ込めテストを実行することができます。これは仮想実装よりもはるかに高速です。検索がはるかに高速された第2のファイルを読み込むときに次に

S = {tuple(line) for line in csv.reader(File1)} 

+0

@Abrahms:助けてくれてありがとう。あなたは詳細を教えていただけますか? File1:行の3つのフィールドはすべてタプルを作成します。それ以降は私は追従しなかった。私のプログラミングレベルは、初心者として最もよく説明することができます。 – Bade

+0

行を解析すると、 '[a、b、c]'という形式になります。これは 'list'です。それを 'tuple'コンストラクタに渡すと' tuple'になります。 'sometuple = tuple(somelist)' –

+0

@ IgnacioVazquez-Abramsアイデアの実装については私の答えを見てください。 (おそらくより効率的な集合の代わりにリストを使うが、あなたはその考えを得る。) –

3

以下は、あなたがお勧めのように最初のファイルの集合の内包表記を使用してハッシュを作成します。

for line in csv.reader(File2): 
    key = tuple(line[:3]) 
    if key in S: 
     print(line) 
+1

上のような集合の解説のための+1。 –

関連する問題