【问题标题】:Using awk, calculate average of rows based on string in 2nd and 5th column and value in 3rd column, and append result使用 awk,根据第 2 列和第 5 列中的字符串和第 3 列中的值计算行的平均值,并附加结果
【发布时间】:2017-05-29 15:49:58
【问题描述】:

这是Using awk, how to convert dates to week and quarter?的变体

输入data.txt:

a;2016-04-25;10;2016-w17;2016-q2
b;2016-04-25;20;2016-w17;2016-q2
c;2016-04-25;30;2016-w17;2016-q2
d;2016-04-26;40;2016-w17;2016-q2
e;2016-07-25;50;2016-w30;2016-q3
f;2016-07-25;60;2016-w30;2016-q3
g;2016-07-25;70;2016-w30;2016-q3

想要的 output.txt:

a;2016-04-25;10;2016-w17;2016-q2;50
b;2016-04-25;20;2016-w17;2016-q2;50
c;2016-04-25;30;2016-w17;2016-q2;50
d;2016-04-26;40;2016-w17;2016-q2;50
e;2016-07-25;50;2016-w30;2016-q3;180
f;2016-07-25;60;2016-w30;2016-q3;180
g;2016-07-25;70;2016-w30;2016-q3;180

因此,计算有数据的天数的季度平均值并附加结果。

2016 年第二季度的平均值计算如下:

(10+20+30+40)/2 = 50     ("2" is the number_of_unique_dates for that quarter)

2016 年第三季度的平均值为:

(50+60+70)/1 = 180

这是我正在进行的工作,似乎非常接近最终解决方案, 但不确定如何获取“唯一日期数”(第 2 栏) 并用作除数?

awk '
BEGIN { FS=OFS=";" }
NR==FNR { s[$5]+=$3; next }
{ print $0,s[$5] / need_num_of_unique_dates_here }
 ' output.txt output.txt 

知道如何获取每季度的“唯一日期数”吗?

【问题讨论】:

  • @EdMorton 感谢您指出这一点!用字符串替换模式。
  • 我从上一个问题中的输入开始,但问题变得很长,所以为了使其紧凑,我选择了上面的数据..
  • 是的,我完全同意!

标签: awk pattern-matching average calculated-columns


【解决方案1】:
$ cat tst.awk
BEGIN { FS=OFS=";" }
$5 != p5 { prt(); p5=$5 }
{ lines[++numLines]=$0; dates[$2]; sum+=$3 }
END { prt() }
function prt(   lineNr) {
    for (lineNr=1; lineNr<=numLines; lineNr++) {
        print lines[lineNr], sum/length(dates)
    }
    delete dates
    numLines = sum = 0
}

$ awk -f tst.awk file
a;2016-04-25;10;2016-w17;2016-q2;50
b;2016-04-25;20;2016-w17;2016-q2;50
c;2016-04-25;30;2016-w17;2016-q2;50
d;2016-04-26;40;2016-w17;2016-q2;50
e;2016-07-25;50;2016-w30;2016-q3;125
f;2016-07-25;60;2016-w30;2016-q3;125
g;2016-07-25;70;2016-w30;2016-q3;125
h;2016-04-01;70;2016-w30;2016-q3;125

【讨论】:

    【解决方案2】:

    另一个gawk解决方案:

    awk -F';' '{ a[$5][$2]+=$3; r[NR]=$0; q[NR]=$5 }
         END { 
               for (i in a) { s=0; len=length(a[i]); 
                   for (j in a[i]) { s += a[i][j] } 
                   a[i]["avg"] = s/len 
               } 
               for (n=1;n<=NR;n++) { print r[n],a[q[n]]["avg"] }
         }' OFS=";" file
    

    输出:

    a;2016-04-25;10;2016-w17;2016-q2,50
    b;2016-04-25;20;2016-w17;2016-q2,50
    c;2016-04-25;30;2016-w17;2016-q2,50
    d;2016-04-26;40;2016-w17;2016-q2,50
    e;2016-07-25;50;2016-w30;2016-q3,180
    f;2016-07-25;60;2016-w30;2016-q3,180
    g;2016-07-25;70;2016-w30;2016-q3,180
    

    • a[$5][$2]+=$3 - 多维数组,汇总某个季度

    • 内每个唯一日期的值
    • len=length(a[i]) - 确定某个季度内唯一日期的数量

    • for(j in a[i]){ s+=a[i][j] } - 对四分之一内所有日期的值求和

    • a[i]["avg"]=s/len - 计算平均值

    【讨论】:

    • 感谢您的解决方案,由于某种原因,我的输出中行的输出顺序发生了变化?我使用 GNU Awk 4.0.1。
    • d,e,f,g,a,b,c 而不是 a,b,c,d,e,f,g。然而,这些行看起来是正确的。
    • @Markus,好的,知道了。固定
    • OFS 设置的一个小东西,可以更改为 ;
    • @Markus,是的,偶尔错过,已修复
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-01-26
    • 1970-01-01
    • 2019-09-12
    • 2022-01-23
    • 2014-04-29
    • 2021-07-14
    • 1970-01-01
    相关资源
    最近更新 更多