2017-02-15 14 views
0

このアルゴリズムを実行するより良い方法があるのか​​どうか疑問に思っていました。私はこのタイプの操作をかなり頻繁に行う必要があることを知っています。現在、私はそれがn^2アルゴリズムと考えられるので、何時間もかかります。私はそれを下に添付します。この検索アルゴリズムを効率的に行う方法はありますか?

import csv 

with open("location1", 'r') as main: 
    csvMain = csv.reader(main) 
    mainList = list(csvMain) 

with open("location2", 'r') as anno: 
    csvAnno = csv.reader(anno) 
    annoList = list(csvAnno) 

tempList = [] 
output = [] 

for full in mainList: 
    geneName = full[2].lower() 
    for annot in annoList: 
     if geneName == annot[2].lower(): 
      tempList.extend(full) 
      tempList.append(annot[3]) 
      tempList.append(annot[4]) 
      tempList.append(annot[5]) 
      tempList.append(annot[6]) 
      output.append(tempList) 

     for i in tempList: 
      del i 

with open("location3", 'w') as final: 
    a = csv.writer(final, delimiter=',') 
    a.writerows(output) 

私は15,000の文字列をそれぞれ含む2つのCSVファイルを持っている、と私はそれぞれの列を比較するために探していますし、それらが一致した場合、最初の終わりに2つ目のCSVファイルの終わりを連結します。どんな助けでも大歓迎です!

ありがとうございます!

+0

Pro:ネイティブライブラリで動作し、外部依存関係はありません。 Con:おそらくPandasで(以下に述べるように)はるかに簡単かつ迅速に行うことができます。比較と追加の両方(コードの3行か4行だと思います) – Kelvin

答えて

2

これは、この方法より効率的にする必要があります:

import csv 
from collections import defaultdict 

with open("location1", 'r') as main: 
    csvMain = csv.reader(main) 
    mainList = list(csvMain) 

with open("location2", 'r') as anno: 
    csvAnno = csv.reader(anno) 
    annoList = list(csvAnno) 

output = [] 
annoMap = defaultdict(list) 

for annot in annoList: 
    tempList = annot[3:] # adapt this to the needed columns 
    annoMap[annot[2].lower()].append(tempList) # put these columns into the map at position of the column of intereset 

for full in mainList: 
    geneName = full[2].lower() 
    if geneName in annoMap: # check if matching column exists 
    output.extend(annoMap[geneName]) 

with open("location3", 'w') as final: 
    a = csv.writer(final, delimiter=',') 
    a.writerows(output) 

あなたは一度だけ、各リストを反復処理する必要があるので、それは、より効率的です。辞書のルックアップは平均でO(1)なので、基本的に線形アルゴリズムが得られます。

+2

あなたの変更がより効率的になる理由を説明すると、*役立つかもしれません。 – Paul

+0

美しい!マップされた値だけがファイルに出力されますが、これはほぼ完璧でした。 * annoMap [geneName] *と一緒に* full *変数を追加して長い文字列を1つ作成するのは簡単な修正でした。どうもありがとう! –

1

簡単な方法の1つは、Pandasのようなライブラリを使用することです。組み込み関数はかなり効率的です。

pandas.read_csv()を使用してcsvをデータフレームに読み込んだ後、pandas関数でcsvを操作できます。

たとえば、Pandas.merge()を使用して、特定の列の2つのデータフレーム(別名2つのcsvファイル)をマージし、必要のないものをドロップすることができます。

データベースに関する知識がある場合は、ここでのロジックは非常に似ています。

0

ありがとうございました。これは私が使用した最終的なスクリプトであり、他の人を助けるために投稿すると考えました。再度、感謝します!

import csv 
from collections import defaultdict 

with open("location1", 'r') as main: 
    csvMain = csv.reader(main) 
    mainList = list(csvMain) 

with open("location2", 'r') as anno: 
    csvAnno = csv.reader(anno) 
    annoList = list(csvAnno) 

output = [] 
annoMap = defaultdict(list) 

for annot in annoList: 
    tempList = annot[3:] # adapt this to the needed columns 
    annoMap[annot[2].lower()].append(tempList) # put these columns into the map at position of the column of intereset 

for full in mainList: 
    geneName = full[2].lower() 
    if geneName in annoMap: # check if matching column exists 
    list = annoMap[geneName] 
    full.extend(list[0]) 
    output.append(full) 

with open("location3", 'w') as final: 
a = csv.writer(final, delimiter=',') 
a.writerows(output) 
関連する問題