データファイルがあります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.tsv
。total_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