私はこれがそれをよりよく説明すると思います。
次のような行列構造(ファイル)があります。
ファイル1
____ snp1 snp2 snp3 snp4
snp1 1 0.3 0.4 0.5
snp2 0.3 1 0.4 0.5
snp3 0.4 0.4 1 0.5
snp4 0.5 0.5 0.5 1
私はこれを変えたいファイル1入力するファイル2:
snp1 snp1 1
snp1 snp2 0.3
snp1 snp3 0.4
snp1 snp4 0.5
snp2 snp2 1
snp2 snp3 0.4
snp2 snp4 0.5
snp3 snp3 1
snp3 snp4 0.5
snp4 snp4 1
私は理解できることを願っていますが、他のどの形式で質問するのかわかりません。私の実際のファイルでは、ファイルはfile1よりも大きいです。
ありがとうございます。
答え1
目的の出力に応じて、上三角関数値のみを印刷します。
awk '
NR==1 {
split($0,hdr," "); next
}
{
for (i=NR;i<=NF;i++) {print $1 FS hdr[i] FS $i}
}
' file
snp1 snp1 1
snp1 snp2 0.3
snp1 snp3 0.4
snp1 snp4 0.5
snp2 snp2 1
snp2 snp3 0.4
snp2 snp4 0.5
snp3 snp3 1
snp3 snp4 0.5
snp4 snp4 1
または等しくPerlを使用して
perl -alne '
if ($. == 1) {
@hdr = @F;
} else {
for $i ($.-1 .. $#F) {
print join " ", $F[0], $hdr[$i], @F[$i];
}
}' file
上三角形だけでなく、行列全体が必要な場合は、ループの開始インデックスを変更して(awkバージョンから)を(perlバージョンから)for
に置き換えます。NR
2
$.-1
1
答え2
修正する
今制限はありません。
#!/bin/bash
INPUT=File1
declare -a fields
fields=( $(head -n1 "$INPUT") )
i=0
while read -r line; do
values=( $line )
for ((j=++i; j<${#values[@]}; j++)); do
echo -e "${fields[$i]}" "${fields[$j]}"'\t'"${values[$j]}"
done
done < <( tail -n+2 "$INPUT")
答え3
これは使いやすくなければなりませんawk
。
$ awk -f script.awk file1.txt
snp1 snp1 1
snp1 snp2 0.3
snp1 snp3 0.4
snp1 snp4 0.5
snp2 snp1 0.3
snp2 snp2 1
snp2 snp3 0.4
snp2 snp4 0.5
snp3 snp1 0.4
snp3 snp2 0.4
snp3 snp3 1
snp3 snp4 0.5
snp4 snp1 0.5
snp4 snp2 0.5
snp4 snp3 0.5
snp4 snp4 1
コンテンツscript.awk
。最初の行をスキップし、必要に応じて残りの部分をフォーマットします。
$ cat script.awk
{
if (NR == 1) next;
print $1" snp1 "$2;
print $1" snp2 "$3;
print $1" snp3 "$4;
print $1" snp4 "$5;
}
コンテンツfile1.txt
$ cat test.txt
____ snp1 snp2 snp3 snp4
snp1 1 0.3 0.4 0.5
snp2 0.3 1 0.4 0.5
snp3 0.4 0.4 1 0.5
snp4 0.5 0.5 0.5 1
以下のように出力を新しいファイルにリダイレクトできます。
awk -f script.awk file1.txt > file2.txt