100個のファイルがあり、csv
各ファイルには2つの列が含まれています。最初のものはでtaxonomy
、2番目はですcounts
。各ファイルには約10,000行があります。各ファイルのデータはtaxonomy
部分的にのみ共有され、合計約50,000の固有値があります。taxa
1つのファイルから欠落している項目に値が割り当てられたテーブルにマージする必要があります0
。結果は、50,000行と101列のテーブルでなければなりませんcsv
。tsv
単純化された例は次のとおりです。ファイル 1( R1.csv
):
A,1
B,20
C,30
ファイル 2( R2.csv
):
C,1
D,13
E,15
F,19
ファイル3(R3.csv
):
A,1
B,4
E,2
G,6
H,8
予想される結果:
Taxa,R1,R2,R3
A,1,0,1
B,20,0,4
C,30,1,0
D,0,13,0
E,0,15,2
F,0,19,0
G,0,0,6
H,0,0,8
bashスクリプトを使ってこれを行う方法を知っていますか?
ベストアンサー1
私はawk
これを使用して複数のファイルを一度に処理します。
sed 's/,R[1-9]\+\.csv:/,/g' <(awk -v HEADER="$(printf ",%s:" R{1..3}.csv)" -F, '
{ seen[$1]=seen[$1]","FILENAME":"$2; }
END { print HEADER; for (x in seen) print x seen[x]}' R{1..3}.csv \
|awk -F, 'NR==1{split($0,arr,/,/);next} {SEP=""; fld=1;
for (x in arr){printf ($0 ~ arr[x])?SEP""$(fld++):",0";SEP=","};print ""}')
出力:
A,1,0,1
B,20,0,4
C,30,1,0
D,0,13,0
E,0,15,2
F,0,19,0
G,0,0,6
H,0,0,8
コード分析:
awk -F, '{ seen[$1]=seen[$1]","FILENAME":"$2; }
END{ print HEADER; for (x in seen) print x seen[x] }' R{1..3}.csv
コードの主要部分は、すべてのファイルの2番目の列をすべて1つに連結し、同じ最初の列を持つファイルに属する値を印刷します。以下は、キーが最初の列で値が追加モードの配列seen
名です。,FILENAME:$2
Inは、seen[$1]=seen[$1]","FILENAME":"$2;
カンマを印刷し、,
その後に現在処理されているFILENAME
ファイルを印刷することを意味します。アッ、コロン:
の後に2番目の列の値が続きます$2
(最初の列が同じ場合)。seen[$1]=...
同じキーインデックスに追加され、=seen[$1]...
同じキー値に保存されます。
このEND
声明は、アッこのブロックはすべてのレコード/行を読み取ると最終的に実行され、forループを使用して配列を繰り返します。ボン印刷して鍵最初とコア値次から。
結果は次のとおりです。
A,R1.csv:1,R3.csv:1
B,R1.csv:20,R3.csv:4
C,R1.csv:30,R2.csv:1
D,R2.csv:13
E,R2.csv:15,R3.csv:2
F,R2.csv:19
G,R3.csv:6
H,R3.csv:8
さて、既存の値がどのファイルから来たのか、どのファイルにこのデータがないのかがわかります。存在しないファイルをデータで埋めるために0
シェルコマンドを使用しました。すべてのファイル名を含むヘッダー行の生成そして配信アッ〜のようにHEADER
-V可変的な:
awk -v HEADER="$(printf ",%s:" R{1..3}.csv)" ...
HEADER
後でこの行を使用します0
。現在の入力形式は次のとおりです。
$ awk -v HEADER="$(printf ",%s:" R{1..3}.csv)" -F, '
{ seen[$1]=seen[$1]","FILENAME":"$2; }
END { print HEADER; for (x in seen) print x seen[x]}' R{1..3}.csv
,R1.csv:,R2.csv:,R3.csv:
A,R1.csv:1,R3.csv:1
B,R1.csv:20,R3.csv:4
C,R1.csv:30,R2.csv:1
D,R2.csv:13
E,R2.csv:15,R3.csv:2
F,R2.csv:19
G,R3.csv:6
H,R3.csv:8
次に、以下の他のものを使用しました。アッ終了しないファイルデータを埋めるスクリプト、0
質問に対する他の回答からこのデータをコピーしました。「列に基づいて書式設定し、不足しているデータを埋める」。
... |awk -F, 'NR==1{split($0,arr,/,/);next} {SEP=""; fld=1;
for (x in arr){printf ($0 ~ arr[x])?SEP""$(fld++):",0";SEP=","};print ""}'
最後に、sed 's/,R[1-9]\+\.csv:/,/g'
結果の既存のファイル名を単一のコンマに変更するために使用します,
。