同じIDを持つ列の値の累積合計

同じIDを持つ列の値の累積合計

私のデータ型はテキストファイルです。

1     
1 2 
1 2  
1 4  
1 6  
2     
2 1 
2 2  
2 3 
2 4  
3     
3 1 
3 5   
3 9  
3 11  

IDが同じ行(最初の列)に対して、前の行に2番目の列のすべての値を合計した列を追加したいと思います。希望の出力は次のとおりです。

1     
1 2   
1 2   2
1 4   4
1 6   8
2     
2 1   0
2 2   1   
2 3   3
2 4   6
3     
3 1   0
3 5   1
3 9   6
3 11  14

私が達成しようとしているものは次のとおりです。

awk -v OFS='' 'NR == 1 {
   next
}
{
   print $0, (NR > 1 && p1 == $1 ? " " (sum+=p2) : "")
}
{
   p1 = $1
   p2 = $2
}' input > output

ただし、これは同じIDの値だけでなく、2列のすべての値を合計したものです。したがって、ID = 1の出力は正確ですが、明らかに悪くなります。

1  2
1  2   2
1  4   4
1  6   8
2
2  1   8
2  2   9
2  3   11
2  4   14
3
3  1   14
3  5   15
3  9   20
3  11  29

正しい部分だけを含めるように合計をどのように変更しますか? (同じIDを持つ行)

答え1

カウントアップ後ろに現在の行を印刷します。

awk '{print $1, $2, sum[$1]; sum[$1] += $2}' file
1
1 2 0
1 2 2
1 4 4
1 6 8
2
2 1 0
2 2 1
2 3 3
2 4 6
3
3 1 0
3 5 1
3 9 6
3 11 15

これは、未定義の変数を空の文字列として扱うか(数字のコンテキストで)ゼロとして扱うawkの利点を利用します。

0増分合計を印刷したくない場合は、次のようにします。

if ($2 != "") sum[$1] += $2

答え2

これは不必要に複雑なアプローチのように見えます。少なくともあなたが示した例では(よく整列している)、次のようにすれば十分です。

$ awk '{ if($1 in a){print $0,a[$1]}else{print} if($2){a[$1]+=$2;}}' file 
1     
1 2 
1 2   2
1 4   4
1 6   8
2     
2 1 
2 2   1
2 3  3
2 4   6
3     
3 1 
3 5    1
3 9   6
3 11 15

02番目にIDを追加したい場合(ID 2と3の場合はこれを実行しましたが、ID 1では実行しなかったため、目的の出力がわかりません)、次の操作を実行できます。

$ awk '{ if($1 in a){print $0,a[$1]}else{a[$1]=0; print} if($2){a[$1]+=$2;}}' file
1     
1 2  0
1 2   2
1 4   4
1 6   8
2     
2 1  0
2 2   1
2 3  3
2 4   6
3     
3 1  0
3 5    1
3 9   6
3 11 15

答え3

$ awk 'NF == 1 { sum = 0 } NF > 1 { $(NF+1) = sum; sum += $2 }; 1' file
1
1 2 0
1 2 2
1 4 4
1 6 8
2
2 1 0
2 2 1
2 3 3
2 4 6
3
3 1 0
3 5 1
3 9 6
3 11 15

列が1つしかない場合は、累積合計がリセットされます。列が複数ある場合は、合計を更新する前に、現在の合計を最後に追加の列として追加します。その後、追加の列を追加または追加せずに現在のレコードが無条件に出力されます(これは1Lonelyが実行するアクションです)。

これは、単一の列を持つ各行が異なる累積合計を計算する必要があるすべての行の前に来るようにファイルがソートされていると仮定します。これが質問にデータが表示される方法です。

関連情報