通常、Rで実行されるコードがありますが、ファイルが大きすぎてawkで同じコマンドを実行しようとしています。
Gene
1列の値をID列(または私の場合は列)でグループ化しようとしています。
私のデータは次のとおりです。
Gene col1 col2 col3
ACE 1 0.4 BP
ACE 2 0.5 DP
RPP-I.1 1 0.01 BP
NOS2 -0.1 0.2 DP
NOS2 1.4 2.5 SP
NOS2 1 1 BP
私はそれを次のようにグループ化したいと思いますGene
:
Gene col1 col2 col3
ACE 1, 2 0.4, 0.5 BP, DP
RPP-I.1 1 0.01 BP
NOS2 -0.1, 1.4, 1 0.2, 2.5, 1 BP, SP, DP
私の実際のデータは、約200列と24972316行を含む14.8GBです。最初はRのdata.tableを試しましたが、ファイルを読み取ろうとしたときにバスエラーが発生しました。
awkを使ってこれを試す方法はありますか?
答え1
GNUを使用する一般的なソリューションawk
は次のとおりです。
gawk 'NR>1{ for (i=2; i<=NF; i++) {
c[i][$1]= c[i][$1]?c[i][$1] s $i:$i;
} next;
}1;
ENDFILE{
for (x in c[2]) {
printf ("%s", x);
for (i=2;i<=NF;i++) { printf ("\t%s", c[i][x]); delete c[i][x]; };
print "";
};
}' s=', ' infile |column -s $'\t' -t
上記のコマンドは、入力ファイルのほとんどすべてをメモリにロードせず、メモリに30GBのRAMがあり、ファイルサイズが15GB程度だと言ったので、少なくとも15GB以上の空きメモリが十分であればそうすることはないようです。問題が発生します。
しかし、以下は解決策ですが、最善の解決策ではありません。 bigfile.txtを小さなファイルに分割し、各ファイルに同じGeneNameを持つ次の上記のコマンドをすべてのファイルawk
に*.small
適用し、出力を追加モードで単一のファイルに保存できます。
私は遺伝子名の分布が同じではない可能性があり、一部は少なく、一部はより多くなる可能性があるため、これは最適ではないと言います。しかし、次のようにすることができます。
最初の列で入力ファイルを小さいサイズに分割します
Gene
。awk 'NR>1{ print >$1".small"; }' bigfile.txt
awk
次に、ファイルに対して上記のコマンドを実行します。*.small
bigfile.txtを分割すると既にスキップされているので、最初に条件を削除してください。NR>1
gawk '{ ... }; ENDFILE{ ... }' s=', ' *.small >>proccedfile
rm *.small
後でファイルを削除してください。
答え2
以下は、sort
ファイル全体を一度だけ処理すると大容量ファイルを処理できるように設計されており、sort
Demand Pagingなどを使用してファイルを処理するように設計されているため、実際に入力全体をメモリに保存する必要はありません。 awkコマンドでは、一度に現在の値のみが保存されるため、$1
メモリの問題はありません。
$ cat tst.sh
#!/usr/bin/env bash
awk -v OFS='\t' '{print (NR>1), NR, $0}' "${@:--}" |
sort -k1,1n -k3,3 -k2,2n |
cut -f 3- |
awk '
BEGIN { OFS="\t" }
NR == 1 { $1=$1; print; next }
$1 != prev { prt() }
{
for (i=2; i<=NF; i++) {
col[i] = (i in col ? col[i] ", " : "") $i
}
}
END { prt() }
function prt( i) {
if ( prev != "" ) {
printf "%s%s", prev, OFS
for (i=2; i<=NF; i++) {
printf "%s%s", col[i], (i<NF ? OFS : ORS)
}
}
delete col
prev = $1
}
'
$ ./tst.sh file
Gene col1 col2 col3
ACE 1, 2 0.4, 0.5 BP, DP
NOS2 1, 1.4, -0.1 1, 2.5, 0.2 BP, SP, DP
RPP-I.1 1 0.01 BP
上記のスクリプトの出力はタブで区切られており、簡単に他のツールを実行でき、スプレッドシートにインポートできるので便利だと思います。視覚的にソートされた列を生成するには、スクリプトの最後に追加しますが、| column -s $'\t' -t
印刷する前に最大フィールド幅を計算するために出力ファイル全体をメモリに読み込む必要がある他のプログラムを導入するため、YMMVを使用することはできません。タブ区切りの出力を許可し、表形式の出力を生成するために使用することはできませんcolumn
。次に、これに関連する新しい質問を投稿してください。
上記のコードは、入力がファイルから来ているかパイプから来ているかに関係なく動作します。