awkを使用して2つのファイルの2つの列を比較し、一致するアイテム数を印刷する方法

awkを使用して2つのファイルの2つの列を比較し、一致するアイテム数を印刷する方法

データファイルがありますA.tsv(フィールド区切り記号= \t)。

id  clade   mutation
243 40A titi,toto,lala
254     
267 40B lala,jiji,jojo

とテンプレートファイルB.tsv(フィールド区切り記号= \t):

40A lala,toto,xixi,xaxa
40B xaxa,jojo,huhu
40C sasa,sisi,lala

A.tsv共通列(クレード)に基づいてテンプレートのバリエーションを比較し、次のように新しいB.tsvファイル()の新しい列で見つかった一致数を表示したいと思います。C.tsv

id  clade   mutation    number
243 40A titi,toto,lala  2
254     
267 40B lala,jiji,jojo  1

次のように2つのファイルを比較する方法を知っています。

awk -F"," -vOFS="," '    
    NR==FNR {
     a[$2]=$3;
     next
    }
    
    { print $0,a[$2] }
' B.tsv A.tsv > C.tsv

しかし、一致を計算する方法がわかりません。良いアイデアがありますか?

2番目の質問:

.NETファイルにどれだけの突然変異があるかについての情報のみを含む新しい列を作成する方法を知りたいですB.tsvtotal_mut次の列の例C.tsv:

id  clade   mutation    number  total_mut
243 40A titi,toto,lala  2   4
254     
267 40B lala,jiji,jojo  1   3

答え1

GNUおよびawk(単語境界アンカー)の使用:\<\>

awk 'BEGIN{ FS=OFS="\t" }
NR==FNR{ mutations[$1] =$2; next }

{
    split($3, muts, "," );
    for(x in muts) { tmp=mutations[$2]; c+=sub( "\\<"muts[x]"\\>", "", tmp) }
}

FNR==1 { c="number" }
{ print $0, (c?c:""); c=0 }' fileB  fileA

出力:

id      clade   mutation        number
243     40A     titi,toto,lala  2
254
267     40B     lala,jiji,jojo  1

2番目のリクエストに対する回答が更新されました。

awk 'BEGIN{ FS=OFS="\t" }
NR==FNR{ mutations[$1] =$2; next }

{
    split($3, muts, "," );
    for(x in muts) { tmp=mutations[$2]; c+=sub( "\\<"muts[x]"\\>", "", tmp) }
    m=1+gsub(",", "", tmp) 
}

FNR==1 { c="number"; m="total_mut" }
{ print $0, (c?c:""), (m>1?m:""); c=m=0 }' fileB  fileA

出力:

id      clade   mutation        number  total_mut
243     40A     titi,toto,lala  2       4
254
267     40B     lala,jiji,jojo  1       3

答え2

awk 'BEGIN{ OFS=FS="\t" }
  NR==FNR{ clade[$1]=$2; next }         # save clade, mutation of B.tsv in array
  FNR==1{ print $0, "number"; next }    # print header
  !($2 in clade){ print; next }         # no match -> print record
  {                                     # else...
     split($3 "," clade[$2], tmp, ",")  # split mutations into tmp array
     for (i in tmp)                     # for all mutations
       if (++num[tmp[i]] > 1)           # if same mutation occurs more than once
         ++count                        # increment counter

     print $0, count                    # print record and count
     delete num                         # reset temporary array
     count=0                            # reset counter
  }
' B.tsv A.tsv > C.tsv

2番目の答え:

3行目を次のように置き換えます。

FNR==1{ print $0, "number", "total_mut"; next }

最後printを次に変更します。

print $0, count, split(clade[$2], tmp, ",")

答え3

アプローチは、Bファイルの分岐点と突然変異で索引付けされた配列を作成することです。次にファイルAの突然変異を繰り返す。

タブ区切りファイルで作業するのは少し面倒です。特にクレードなしで熱数を維持することはさらにそうです。

A ファイルに必要な列番号を cClade と cMut として定義し、データ型全体と一致するように変更します。

その後の質問の場合は、Split()から返されたnMut(バリアント数)を保存し、それを印刷物(タイトルと詳細)に追加します。このバージョンもテストしました。

#! /bin/bash

Match () {  #:: (data, template)

    Awk='
BEGIN { FS = "\t"; Sep = ","; cClade = 20; cMut = 41; }
F == "B" {
    nMut[$1] = split ($2, V, Sep);
    for (j in V) Mut[$1 Sep V[j]];
    next;
}
! $2 { printf ("%s%s%s\n", $0, FS, FS); next; }
FNR == 1 { printf ("%s%s%s%s%s\n", $0, FS, "number", FS, "total_mut"); next; }
{
    n = 0;
    split ($cMut, V, Sep);
    for (j in V) if (($cClade Sep V[j]) in Mut) ++n;
    printf ("%s%s%s%s%s\n", $0, FS, n, FS, nMut[$cClade]);
}
'
    awk -f <( printf '%s' "${Awk}" ) F="B" "${2}" F="A" "${1}"
}

    Match useTemplate.A.tsv useTemplate.B.tsv > useTemplate.C.tsv

答え4

これは、多次元配列を処理するためにGNU awkを使用します。

gawk '
    BEGIN {
        FS = "[\t,]"
        OFS = "\t"
    }
    FILENAME == ARGV[1] {
        for (i = 2; i <= NF; i++)
            B[$1][$i] = 1
        next
    }
    FNR == 1 {
        print $0, "number", "total_mut"
        next
    }
    !($2 in B) {
        print
        next
    }
    {
        count = 0
        for (i = 3; i <= NF; i++)
            if ($i in B[$2])
                count++
        print $0, count, length(B[$2])
    }
' {B,A}.tsv
id      clade   mutation        number  total_mut
243     40A     titi,toto,lala  2       4
254
267     40B     lala,jiji,jojo  1       3

関連情報