列の要素の発生頻度に基づいて行を選択する方法

列の要素の発生頻度に基づいて行を選択する方法

ご覧のとおり、タブで区切られたデータには約4,000行と10列のファイルがあります。

ファイルの2番目の列にはさまざまな組織が記録されます。

samples tissue_s tissue_e tissue_d tissue_category tissue_visa sex study tissue_f age
samples1  ear     CNS      ear       CNS            CNS        male  1   ear 365
samples2  ear     CNS      ear       CNS            CNS        male  1   ear 365
samples3  ear     CNS      ear       CNS            CNS        male  1   ear 365
samples4  ear     CNS      ear       CNS            CNS        male  1   ear 365
samples5  ear     CNS      ear       CNS            CNS        male  1   ear 365
samples6  stomach CNS      ear       CNS            CNS        male  1   ear 365
samples7  stomach CNS      ear       CNS            CNS        male  1   ear 365
samples8  stomach CNS      ear       CNS            CNS        male  1   ear 365
samples9  stomach CNS      ear       CNS            CNS        male  1   ear 365
...
...

10回以上表示されるすべての組織情報を印刷できることを願っています。

しかし、このようにして中間ファイルを生成することは非効率的だと思います。もっと簡潔で効率的な方法がありますか?

cat file | awk '{print $2}' | awk '{a[$0]++}END{for(i in a){if(a[i] > 10){print i}}}' > tmp.txt
grep -wFf tmp.txt file.txt > resule.txt

ベストアンサー1

1つの方法は、入力ファイルを2回処理することです。

awk -F'\t' -v frq=10 -v colId=2 '
  NR==FNR{ count[$colId]++; next }
  count[$colId] >frq
' infile infile

注:カスタムawk変数は、レコードを出力する必要があるターゲット列IDの要素の最小繰り返し頻度を設定および指定するためfrqに使用されます。colId


別の方法は、入力ファイルを処理することです。一度そしてただ数行バッファリングipnutデータが次のように2番目のフィールドにソートされている場合:

awk -F'\t' -v frq=10 -v colId=2 '
function prnt() { if(c>frq) printf("%s", buf); buf=c="" }

prev!=$colId{ prnt() }
{ c++; prev=$colId; buf = buf $0 ORS }

END{ prnt() }' infile

2番目のフィールドでソートされていない場合は、まずソートしてからawkに渡します。

<infile sort -t$'\t' -k2,2 |
awk -F'\t' -v frq=10 -v colId=2 '
function prnt() { if(c>frq) printf("%s", buf); buf=c="" }

prev!=$colId{ prnt() }
{ c++; prev=$colId; buf = buf $0 ORS }

END{ prnt() }'

おすすめ記事