0

次の問題に対処するPythonスクリプトを作成したいと思います。

タブで区切られた2つのファイルがあり、1つにはさまざまな単語の列が1つだけあります。もう1つのファイルには、類似した単語を含む1つの列と、その他の情報の列があります。ただし、最初のファイル内の一部の行には、「///」で区切られた複数の単語が含まれています。他のファイルにも同様の問題がありますが、区切り文字は「|」です。

ファイル#1

RED
BLUE /// GREEN
YELLOW /// PINK /// PURPLE
ORANGE
BROWN /// BLACK

ファイル#2(他の測定値の追加の列が含まれています)

RED|PINK 
ORANGE
BROWN|BLACK|GREEN|PURPLE
YELLOW|MAGENTA

各ファイルを解析して同じ単語を照合し、追加の測定値の列も追加したいと思います。///ただし、最初のファイルと2番目のファイルのを無視して|、各単語がそれ自体で他のリストと比較されるようにします。出力ファイルには、両方のリストに表示される単語の1列だけが含まれ、ファイル2から追加情報が追加されている必要があります。


追加情報/更新:

これがファイル#1の8行です。わかりやすくするために上記の色の名前を使用しましたが、これが実際の単語です。これらは「記号」です。

ANKRD38  
ANKRD57  
ANKRD57
ANXA8 /// ANXA8L1 /// ANXA8L2  
AOF1  
AOF2  
AP1GBP1  
APOBEC3F /// APOBEC3G  

ファイル#2の1行を次に示します。file1の各シンボルを実行し、file2の5列目にある「同義語」のいずれかと一致するかどうかを確認します(ここでは同義語はA1B | ABG|です)。 GAP | HYST2477)。file1のシンボルがcol5file 2の同義語のいずれかに一致する場合は、file1のシンボルに追加情報(file2の他の列)を追加して、1つの大きな出力ファイルを作成する必要があります。

9606  '\t'    1 '\t'    A1BG  '\t'   -   '\t'       A1B|ABG|GAB|HYST2477'\t'    HGNC:5|MIM:138670|Ensembl:ENSG00000121410|HPRD:00726    '\t' 19   '\t'  19q13.4'\t' alpha-1-B glycoprotein '\t' protein-coding '\t' A1BG'\t'    alpha-1-B glycoprotein'\t'  O '\t'  alpha-1B-glycoprotein '\t'  20120726

File2は22,000KBで、ファイル1ははるかに小さいです。提案されているようにdictを作成することを考えましたが、各ファイルの異なる区切り文字にとらわれ続けています。これまでの質問と支援に感謝します。

4

3 に答える 3

0

編集

以下のコメントの後、これがあなたがやりたいことだと思います。その中の何かがあなたに役立つ場合に備えて、私は以下の元の投稿を残しました。

だから、あなたは次のことをしたいと思います。まず、このコードはfile1からすべての個別の同義語をaに読み込みます。setこれは、重複を自動的に削除し、検索が非常に高速であるため、便利な構造です。辞書のようなものですが、キーのみで値はありません。重複を削除したくない場合は、少し変更する必要があります。

file1_data = set()
with open("file1.txt", "r") as fd:
    for line in fd:
        file1_data.update(i.strip() for i in line.split("///") if i.strip())

次に、file2を実行して、一致するものを探します。

with open("file2.txt", "r") as in_fd:
    with open("output.txt", "w") as out_fd:
        for line in in_fd:
            items = line.split("\t")
            if len(items) < 5:
                # This is so we don't crash if we find a line that's too short
                continue
            synonyms = set(i.strip() for i in items[4].split("|"))
            overlap = synonyms & file1_data
            if overlap:
                # Build string of columns from file2, stripping out 5th column.
                output_str = "\t".join(items[:4] + items[5:])
                for item in overlap:
                    out_fd.write("\t".join((item, output_str)))

つまり、これはfile2と出力ファイルを開きます。file2の各行を調べ、最初に少なくとも列5を持つのに十分な列があることを確認します。そうでない場合は、その行を無視します(エラーを出力することをお勧めします)。

次に、列5をで分割し、そのリスト(と呼ばれる)からを|作成します。これは、file1のすべての同義語の前のセットとの交差を非常に高速に見つけることができるため便利です。この交差はに格納されます。setsynonymssetoverlap

次に、重複があったかどうかを確認します。重複していない場合は、file1に同義語が見つからなかったため、この行を無視します。このチェックは主に速度を対象としているため、この行で使用しない場合は、出力文字列をわざわざ作成する必要はありません。

重複があった場合は、同義語に追加する列の完全なリストである文字列を作成します。複数の一致がある場合でも、一致ごとに同じであるため、これを文字列として1回作成できます。すべてfile2の行から取得されます。これは、毎回文字列として作成するよりも高速です。

次に、file1で一致した同義語ごとに、同義語である行、タブ、file2の残りの行を出力に書き込みます。タブで分割するため、を使用してタブを元に戻す必要があり"\t".join(...)ます。これは、列5を削除したいというのが正しいことを前提としています。削除したくない場合は、最後に改行を取り除いたfile2の行を使用できるため、さらに簡単です。

うまくいけば、それはあなたが必要とするものに近いですか?

元の投稿

ファイルのサイズはわかりませんが、メモリに収まるほど小さいと思います。そうでない場合、問題は少し複雑になります。

したがって、最初のステップはおそらくファイル#2を開いてデータを読み込むことです。次のようなコードでそれを行うことができます:

file2_data = {}
with open("file2.txt", "r") as fd:
    for line in fd:
        items = line.split("\t")
        file2_data[frozenset(i.strip() for i in items[0].split("|"))] = items[1:]

これによりfile2_data、単語をその行の残りの項目のリストにマップする辞書として作成されます。以前のコメントで述べたように、単語が繰り返されるかどうか、そしてそれをどのように処理したいかについても考慮する必要があります。

この後、最初のファイルを読み取り、そのファイル内の各単語にデータを添付できます。

with open("file1.txt", "r") as fd:
    with open("output.txt", "w") as fd_out:
        for line in fd:
            words = set(i.strip() for i in line.split("///"))
            for file2_words, file2_cols in file2_data.iteritems():
                overlap = file2_words & words
                if overlap:
                    fd_out.write("///".join(overlap) + "\t" + "\t".join(file2_cols))

最終的にoutput.txtは、2つのファイルの単語のリストに少なくとも1つの共通の単語があり、最初の項目がで区切られた共通の単語である1つの行になります///。その出力ファイルの他の列は、ファイル#2の一致した行の他の列になります。

それがあなたが望むものでない場合は、もう少し具体的にする必要があります。

余談ですが、これを行うには、上記で概説したO(N ^ 2)アプローチよりも効率的な方法があります(つまり、ファイル全体で、他の行と同じ回数実行されます)が、より詳細な方法が必要です。線をどのように一致させたいかに関する情報。

たとえば、単語をその単語が出現する行のリストにマッピングする辞書を作成できます。これにより、上記で実行した完全なスキャンよりも、一致する行をチェックする方がはるかに高速になります。これは、行間のオーバーラップが必要なように見えるという事実によって少し厄介にレンダリングされます。したがって、上記の単純なアプローチで、詳細がなくても十分だと思いました。

于 2013-01-12T00:30:42.280 に答える
0
  1. ファイルI/Oについては、 http://docs.python.org/2/tutorial/inputoutput.htmlを参照してください。

  2. 各ファイルの各行をループします

    file1set = set(file1line.split('///'))

    file2set = set(file2line.split('|'))

    wordsineach = list(file1set&file2set)

splitは色名の配列を作成します

set()はそれをセットに変換するので、各行の違いを簡単に比較できます

  1. 'wordsineach'をループして、新しいファイルに書き込みます
于 2013-01-12T00:20:48.970 に答える
0

str.replace関数を使用する

with open('file1.txt', 'r') as f1:
    content1 = f1.read()
    content1 = content1.replace(' /// ', '\n').split('\n')
with open('file2.txt', 'r') as f2:
    content2 = f2.read()
    content2 = content1.replace('|', '\n').split('\n')

次に、リスト内包表記を使用します

common_words = [i for i in content1 if i in content2]

ただし、各ファイルの単語がどれも同じでないことがすでにわかっている場合は、交差点を設定して作業を楽にすることができます

common_words = list(set(content1) & set(content2))

次に、残りを別のファイルに出力します。

common_words = [i + '\n' for i in common_words]  #so that we print each word on a new line

with open('common_words.txt', 'w') as f:
    f.writelines(common_words)

「追加情報」については、フォーマット等を教えていただけないのでお役に立てません。

于 2013-01-12T00:24:16.203 に答える