具有相同 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

然而,这是对第 2 列中的所有值求和,而不仅仅是具有相同 ID 的值。所以 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

如果您想0在第二次看到 ID 时添加 a (您想要的输出对此不清楚,因为您已为 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最后所做的事情)。

这假设文件以这样的方式排序:具有单列的每一行位于应计算不同累积和的所有行之前。这就是问题中数据的呈现方式。

相关内容