質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
for

for文は、様々なプログラミング言語で使われている制御構造です。for文に定義している条件から外れるまで、for文内の命令文を繰り返し実行します。

if

if文とは様々なプログラミング言語で使用される制御構文の一種であり、条件によって処理の流れを制御します。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

Q&A

解決済

2回答

4631閲覧

同じファイルを2回、for構文で処理したい

kompeito

総合スコア13

for

for文は、様々なプログラミング言語で使われている制御構造です。for文に定義している条件から外れるまで、for文内の命令文を繰り返し実行します。

if

if文とは様々なプログラミング言語で使用される制御構文の一種であり、条件によって処理の流れを制御します。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

0グッド

0クリップ

投稿2018/11/20 06:51

お世話になっております。
Pythonを使って、以下のような処理をしたいと考えています。

  • 読み込ませているファイル形式

['ファイル名','条件','詳細(succeed, failなど)']

  • やりたいこと

①'条件'==1のとき、ファイル名を抜き出してリストに追加(remove_list)
②詳細が'succeed'かつ①のリストにファイル名が含まれていないものだけをファイルに書き出し

ファイル名が重複しているのですが、1つでも'条件'==1のデータが存在するファイルは、
その他のデータが②を満たしていても除外したい…という意味合いです。

【例】
['file1',1,'succeed']
['file1',0,'succeed']
['file1',0,'fail']
['file2',0,'succeed']
['file2',0,'fail']

この場合は['file2',0,'succeed']だけを取り出したいと考えています。

  • 試してみたコード

Python

1in_file = ('filename', 'r') 2out_file_1 = ('filename', 'w') 3out_file_2 = ('filename', 'w') 4 5remove_list = [] 6 7for read1 in in_file: 8 if read1[1]==1: 9 remove_list.append(read1[0]) 10 else: 11 pass 12 13for read2 in in_file: 14 if not (read2[2]=='fail' or (read2[0] in remove_list)): 15 out_file_1.write(read2) 16 else: 17 out_file_2.write(read2) 18 19out_file_1.close() 20out_file_2.close() 21in_file.close()
  • 問題点

・この書き方だと、1つ目のfor構文まではうまくいき、remove_listの作成はできるのですが、2つ目が処理されません。
Jupyter notebookで、1つ目のfor構文だけを流した後に、2つ目を単独で流すと、正常にファイルを処理することができます。
これを1つのPythonスクリプトにするには、どのように記載したら良いでしょうか?

・読み込ませるファイルサイズが大きく(13GB)、処理に時間がかかってしまうため、もっと簡潔に記載できないかと悩んでいます。

ご意見いただけたら嬉しいです。
よろしくお願いいたします。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

can110

2018/11/20 07:09 編集

読込ファイルの行の並び順ですが、1列目のファイル名の昇順で並んでいますか?それとも並び順は不定ですか?また、取り出したいのは行全体「['file2',0,'succeed']」ですか?あるいはファイル名「'file2'」だけでもよいですか?
kompeito

2018/11/20 07:21

ご返信ありがとうございます。同じファイル名のデータは連続して並んでいるのですが、ファイル名の並び順は不定です。
guest

回答2

0

ベストアンサー

同じファイル名は固まって存在しているのであれば…
入力ファイルを行毎に読み込んで、ファイル名の切り替わり毎に適切に合否判定して合格ファイル名を出力すればよいです。
ループは1回で済みますし、メモリも1行分しか必要ありません。

Python

1fin = open('inp.csv','r') 2fok = open('ok.csv','w') # 合格 3fng = open('ng.csv','w') # 不合格 4 5# 現在判定対象のファイル名、条件'1'ありか、詳細`succeed`ありか 6file,is_one,is_succeed = '',False,False 7 8line = fin.readline().strip() 9while line: 10 f,no,desc = line.split(',') # ファイル名,条件,詳細 11 line = fin.readline().strip() 12 13 # ファイル名の切り替わり 14 # 現在判定中ファイル名の処理 15 if file != f: 16 if len(file) > 0: 17 if (not is_one) and is_succeed: 18 fok.write(file+'\n') 19 else: 20 fng.write(file+'\n') 21 file,is_one,is_succeed = f,False,False 22 23 if no == '1': 24 is_one = True 25 if desc == 'succeed': 26 is_succeed = True 27fin.close() 28 29# 最後の行 30if len(file) > 0: 31 if (not is_one) and is_succeed: 32 fok.write(file+'\n') 33 else: 34 fng.write(file+'\n') 35 36fok.close() 37fng.close()

投稿2018/11/20 08:12

編集2018/11/20 09:20
can110

総合スコア38258

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

kompeito

2018/11/20 09:01

丁寧なご回答をいただき、ありがとうございます。 ファイル形式を簡便に記載してしまったのですが、実は今回使用しているファイルは遺伝子情報を扱う bamファイルというもので、バイナリ形式のため、pysamモジュールを使って読み込んでおります。 https://pysam.readthedocs.io/en/latest/ import pysam in_file = pysam.AlignmentFile('filename.bam', 'rb') out_file_1 = pysam.AlignmentFile('filename.bam', "wb", template = in_file) out_file_2 = pysam.AlignmentFile('filename.bam', "wb", template = in_file) 今回ご回答いただいたスクリプトだと、処理時間も大幅に短縮できると思うのですが、 まだpythonを使用し始めたばかりで、このpysamモジュールと併用できるかがわかりません… 少し試してみたいと思いますので、結果が出次第、またご返信させてください。 よろしくお願いいたします。
can110

2018/11/20 09:21

回答コード、成否ファイル名を別ファイルに書き出すように修正しました。 回答した手法は非常に基本的なテクニックですので、応用はきくと思います。
kompeito

2018/11/28 05:54

ご返信が遅くなり申し訳ありません。 いただいたスクリプトで欲しいデータを得ることができました。 また、これまで自分がやっていた方法では1時間近く処理にかかっていましたが、今回のスクリプトでは2分で処理を終えることができました。 とても参考になりました。 本当にありがとうございました!
kompeito

2018/11/28 08:22 編集

度々申し訳ありません。 このスクリプトでは、 『1つでも'条件'==1のデータが存在するファイルは、その他のデータが"succeed"を満たしてしていても除外したい』という条件は考慮されていますでしょうか…? 【例】 ['file1',1,'succeed'] ['file1',0,'succeed'] ['file1',0,'succeed'] だった場合、file1はすべて除外する、という意味合いです。
can110

2018/11/28 08:43

ちょっと問題忘れかけてますが… 『1つでも'条件'==1のデータが~』という条件が、質問で提示された条件と同じであれば、満たします。 具体的に簡単な例で実行した結果が提示されている条件を満たしていなければ、その条件を変える必要あると思います。
kompeito

2018/11/29 05:10 編集

ご返信いただきありがとうございます。 返信に時間がかかってしまい申し訳ありません… 条件はもう少し検討が必要そうですが、道は見えてきた気がします。 以前頂いたコメントで質問しそこねてしまったのですが、行全体を取り出したい場合は fok.write(file+'\n')をどのように変更したら良いでしょうか…? ['file1',0,'succeed'] ['file1',0,'succeed'] ['file1',0,'succeed'] であった場合、ファイル名が重複していても、すべての行を取り出したいと考えています。
can110

2018/11/29 05:22

条件については了解です。条件は明文化さえ出来れば、あとはそれをコードに落としこむだけです。 が、その明文化が意外と難しいですし、それはご本人しか出来ません。頑張ってください。 行全体の取り出しについては、行全体のデータを、file変数と同様にline変数(リスト)なりに保持しておき、file変数と同じタイミングで出力すればよいかと思います。
kompeito

2018/11/29 05:29

ご返信、本当にありがとうございます。 このpysamモジュールを使ってしまうと、データが独特のオブジェクト内に保存されてしまうようで、 readlineが使えなかったり、リスト化できなかったりと、慣れるまでなかなか扱いにくそうです… 通常のテキスト形式で読み込むとうまく行くようなので、まずはこのやり方で進めてみようと思います。 度々の質問にも丁寧にご対応くださり、本当にありがとうございました!
guest

0

2つ目の処理が行われないのは、ファイルがすでに終端まで読みだされているからです。
一旦ファイルを閉じて、再度開いてから2つ目の処理を行えばいいのですが、13GBものファイルを2回も読み込むのは時間がかかります。
対応策としては、最初の処理で条件==1のリストを作るだけでなく、succeedのリストも作成して、2つ目の処理をsucceedリストの中から条件==1リストに含まれているものを除外する処理に変更してはどうでしょうか。

追記

failまたは条件==1のものも別のファイルにリストアップする必要があるのであれば、succeedリストとfailリストを作成して、succeedリストから条件==1リストにあるものをfailリストに移動すればいいんじゃないかと思います。
順番を維持したい場合は、リストに番号を付与して、最後に番号でソートするといった方法があります。

投稿2018/11/20 07:13

編集2018/11/20 07:19
m-take

総合スコア249

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

kompeito

2018/11/20 09:07

ご回答いただきありがとうございます。 以下のようなイメージであっておりますでしょうか…? remove_list = [] pass_list = [] for read in in_file: if read[1]==1: remove_list.append(read[0]) else: if not read[2]=='fail': pass_list.append(read[0]) else: pass if read[0] in pass_list and (not read[0] in remove_list): out_file_1.write(read) else: out_file_2.write(read)
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問