
これは問題に対する優雅な解決策を見つけることであり、私は効果的な解決策を持っていると思います。私のUbuntuコンピュータには、次のような入力ファイル形式(タブ区切り)があります。
AC003665.1 17 47813266 AGCAGGCGCA 83
RIOK3 18 23453502 GCAAGGCCCC 52
UBE2Z 17 48910880 CTAAGGATCC 48
CSNK1D 17 82251379 AATTTAGCCA 68
CSNK1D 17 82251379 AATTTCTTGT 38
SMURF1 7 99143726 GACAGATTGG 74
SMURF1 7 99143726 GACAGATTGG 61
RIOK3 18 23453502 GCAAGACTTT 69
フィールド3が発生するたびに、1つの行、つまりフィールド5で最も高い値を持つ行を取得したいと思います。したがって、出力は次のようになります。
AC003665.1 17 47813266 AGCAGGCGCA 83
CSNK1D 17 82251379 AATTTAGCCA 68
UBE2Z 17 48910880 CTAAGGATCC 48
SMURF1 7 99143726 GACAGATTGG 74
RIOK3 18 23453502 GCAAGACTTT 69
順序は私の目的とは関係ありません。まず、フィールド5でソートしてから、フィールド3でソートするソリューションを見つけました。これがうまくいくと思います。
sort -k 5,5nr input | sort -u -k 3,3n > output
これはすべてのテストファイルで機能し、どのような場合でも機能する必要があると思います。これは、フィールド3のすべての値に対してソートが最初にフィールド5の値が最も高い行をチェックして保持するためです。
しかし、この問題に対するもう少しエレガントな(多分より確実な)解決策があるべきだと思います。助けてくれてありがとう。
答え1
出力するデータがメモリに入るほど小さい場合
awk '
biggest[$3] < $5 { biggest[$3]=$5 ; saved[$3]=$0 }
END { for (i in saved) { print saved[i] }}'
通常、この方法がより高速で保存する必要があるかどうかを判断するときは、各行を一度見てください。メモリ要件は出力されるデータによって異なりますので、非常に反復的な入力は非常に大きくなる可能性があります。
これは、行ごとに複数の比較が必要なソートソリューションとは対照的です。ソートベースのソリューションは、速度が遅くても大きすぎてメモリに収まらない出力を処理します。
答え2
2番目と3番目のフィールドに基づいてソートし、awk
最大値を維持するために渡します。
$ sort -k 3,3nr -k 5,5rn input | awk '!a[$3]++'
SMURF1 7 99143726 GACAGATTGG 74
CSNK1D 17 82251379 AATTTAGCCA 68
UBE2Z 17 48910880 CTAAGGATCC 48
AC003665.1 17 47813266 AGCAGGCGCA 83
RIOK3 18 23453502 GCAAGACTTT 69
これは、ファイルが一度だけソートされ、ファイル全体をメモリに保存する必要がないという利点があります。しかし、私は望むIcarusのawkメソッドファイルを一度だけ読み取ればよいので、より高速です。