すべてのイベントとサイズを報告するファイルがあります。上の行の列3が、下の行の列2と同じであると識別できる連続イベントをマージして、その情報を要約しようとしています(列1が同じ場合)。同じ形式で連続した文字列が複数行の場合、列 2 はその列のグループ化の最下位の数字、列 3 はその列のグループ化の最上位の数字、列は単一の行に置き換えられます。 4は、列4のすべての数値の平均(最も近い整数に丸められます)になります。
明確に言えば、最初の列は特定のグループ、2番目の列は開始位置、3番目の列は終了位置、4番目の列は発生回数です。
列の組み合わせは各行ごとに一意であり、列は列1、列2、列3に基づいて事前にソートされています。列 2 の数字は同じであってはいけません/同じであってはいけません。最初の列は同じでもよく、通常同じです。
可能であれば、awkでこれを達成しようとしていますが、試してみましたが失敗しました。私が試したことは次のとおりです。
awk 'BEGIN {OFS=","} NR==1 {print} NR>1 {if ($1==prev && $2==end+1) {sum+=$4; count++; end=$3} else {if (NR>2) {print prev, start, end, int(sum/count+0.5);}; prev=$1; start=$2; end=$3; sum=$4; count=1}} END {print prev, start, end, int(sum/count+0.5)}'
###### reformatted via "awk -o- '...script_body...'"
awk '
BEGIN {
OFS = ","
}
NR == 1 {
print
}
NR > 1 {
if ($1 == prev && $2 == end + 1) {
sum += $4
count++
end = $3
} else {
if (NR > 2) {
print prev, start, end, int(sum / count + 0.5)
}
prev = $1
start = $2
end = $3
sum = $4
count = 1
}
}
END {
print prev, start, end, int(sum / count + 0.5)
}'
入力例:
fgh1,45513382,45513383,43
fgh1,45513383,45513384,44
fgh1,45513384,45513385,44
fgh1,45513385,45513386,43
fgh1,45513386,45513387,43
fgh1,45513387,45513388,44
fgh2,63543512,63543513,44
fgh2,63543513,63543514,41
fgh2,63543514,63543515,44
fgh2,63543515,63543516,44
出力例:
fgh1,45513382,45513388,44
fgh2,63543512,63543516,43
ベストアンサー1
列 1 は同じですが、3 番目の列と次の行の 2 番目の列との間に間隔があるいくつかの入力行を追加します。
$ cat raw.dat
fgh1,45513382,45513383,43
fgh1,45513383,45513384,44
fgh1,45513384,45513385,44
fgh1,45513385,45513386,43
fgh1,45513386,45513387,43
fgh1,45513387,45513388,44
fgh2,63543512,63543513,44
fgh2,63543513,63543514,41
fgh2,63543514,63543515,44
fgh2,63543515,63543516,44 # 3rd column (current line) does not match ...
fgh2,63543524,63543525,20 # 2nd column (next line)
fgh2,63543525,63543526,60
メモ:OPの説明とサンプルデータでこれが起こることができるかどうかは不明です。提案されたコードは引き続き機能する必要があり、削除される可能性があり|| $2 != outcols[3]
ます。
一般的なアプローチ:
- 配列内の次の出力列セットを追跡します。
- 条件が一致しない場合は、配列を印刷して配列を消去し、次の出力行で配列の塗りつぶしを開始します。
アイデアawk
:
awk '
BEGIN { FS = OFS = "," }
function print_line () {
if (outcols[1]) { # if we have something in outcols[1] then ...
for (i=1;i<=3;i++) # loop through 1st three columns and ...
printf "%s%s", outcols[i], OFS # print to stdout then ...
printf "%.0f\n", (sum / count) # calculate/print average; let printf/.0f do the rounding
}
delete outcols # clear array
sum = count = 0 # reset counters
}
($1 != outcols[1]) ||
($2 != outcols[3]) { print_line() }
{ if (! outcols[1]) { # if nothing in outcols[1] then initialize 1st two output columns ...
outcols[1] = $1
outcols[2] = $2
}
outcols[3] = $3
sum += $4
count++
}
END { print_line() } # flush last line to stdout
' raw.dat
これで以下が生成されます。
fgh1,45513382,45513388,44
fgh2,63543512,63543516,43
fgh2,63543524,63543526,40