各行セット(別の列に基づく)から1つの行(列の値に基づいて)を選択します。

各行セット(別の列に基づく)から1つの行(列の値に基づいて)を選択します。

次のファイルがあります。

gene.14977.0.1.p2       NbD023586.1.mrna1       100.0   132     0       0       1       132     1       132     4.9e-72     268.9
gene.14977.0.1.p2       NbD032405.1.mrna1       95.5    132     6       0       1       132     1       132     1.5e-68     257.3
gene.14983.1.1.p1       NbE05064429.1.mrna1     61.4    202     13      3       8       145     530     730     8.6e-51     198.7
gene.14983.1.1.p1       NbD024082.1.mrna1       59.3    209     13      3       8       145     530     737     5.6e-50     196.1
gene.14983.1.1.p1       NbD018021.1.mrna1       59.5    205     18      3       5       145     523     726     3.0e-48     190.3
gene.14986.0.0.p1       NbD007981.1.mrna1       100.0   422     0       0       9       430     1       422     1.8e-256    883.2
gene.14986.0.0.p1       NbD032402.1.mrna1       96.5    430     14      1       1       430     1       429     2.7e-252    869.4
gene.14986.0.0.p1       NbD023991.1.mrna1       85.3    428     61      1       1       428     1       426     2.1e-225    780.0

各遺伝子値(たとえば、最初の列)について、列11(たとえば)gene.14977.0.1.p2の最小値を持つ行のみを維持したいと思います。4.9e-72予想される出力は次のとおりです。

gene.14977.0.1.p2       NbD023586.1.mrna1       100.0   132     0       0       1       132     1       132     4.9e-72     268.9
gene.14983.1.1.p1       NbE05064429.1.mrna1     61.4    202     13      3       8       145     530     730     8.6e-51     198.7
gene.14986.0.0.p1       NbD007981.1.mrna1       100.0   422     0       0       9       430     1       422     1.8e-256    883.2

それはどのように可能ですか?

ベストアンサー1

11番目の列から最小値を持つ行を抽出したい場合遺伝子別にグループ化次に、遺伝子識別子を連想配列のキーとして使用して、awkその遺伝子の最小値を追跡する。

$ awk '{ gene = $1 } min[gene] == "" || min[gene] > $11 { min[gene] = $11; line[gene] = $0 } END { for (gene in line) print line[gene] }' file
gene.14983.1.1.p1       NbE05064429.1.mrna1     61.4    202     13      3       8       145     530     730     8.6e-51 198.7
gene.14977.0.1.p2       NbD023586.1.mrna1       100.0   132     0       0       1       132     1       132     4.9e-72 268.9
gene.14986.0.0.p1       NbD007981.1.mrna1       100.0   422     0       0       9       430     1       422     1.8e-256        883.2

ここでは、各遺伝子の最小値が現れる実際の行を追跡し、最後にその行を印刷します。

プログラムawkの形式は次のとおりです。

{
        # Pick out the gene name
        gene = $1
}

min[gene] == "" || min[gene] > $11 {
        # This gene hase either not been seen before,
        # or its value in column 11 is smaller than
        # what has been seen before (for this gene).
        min[gene] = $11    # save small value from column 11
        line[gene] = $0    # save whole line
}

END {
        # Print all remembered lines.
        for (gene in line)
                print line[gene]
}

メンテナンスが難しいコードが好きな人のための最小化された1行バージョン:

awk 'm[$1]==""||m[$1]>$11{m[$1]=$11;t[$1]=$0}END{for(g in t)print t[g]}' file

sortGNU(科学的表記法で数字を「人間の数字をソートする」)を使用して、同じ結果(おそらく異なる順序で)を得ることもできます。

$ sort -k1,1 -k11,11g file | sort -u -k1,1
gene.14977.0.1.p2       NbD023586.1.mrna1       100.0   132     0       0       1       132     1       132     4.9e-72 268.9
gene.14983.1.1.p1       NbE05064429.1.mrna1     61.4    202     13      3       8       145     530     730     8.6e-51 198.7
gene.14986.0.0.p1       NbD007981.1.mrna1       100.0   422     0       0       9       430     1       422     1.8e-256        883.2

ここで、最初のソートは、行が遺伝子(最初の列)でソートされ、各遺伝子の行が列11に基づいて数値でソートされるようにデータをソートします。次に、2番目はsort各遺伝子の行を選択します(-uこのオプションのおかげで、各ソートキーに対して単一の項目を要求します)。この単一行は各遺伝子の最初の行になり、列11で最も小さい値を持つ行になります(最初の行によるsort)。

sort2番目のプログラムの代わりに短いプログラムを使用できますawk。これは大量のデータに対して少し高速です。

sort -k1,1 -k11,11g file | awk '!seen[$1]++'

おすすめ記事