【问题标题】:Calculate average depending on number of instances on each line - Bash - AWK根据每行上的实例数计算平均值 - Bash - AWK
【发布时间】:2021-05-19 09:18:28
【问题描述】:

当每行的字母数字实例的数量(包括最终的总平均值)有所不同时,您如何计算每行的平均值?

即。 pie.txt:

0.8pie 0.7pie 0.6pie            
34.2pie 34.1pie 35.8pie 
42pie 43pie 43pie
44pie 41pie 38pie
0.8pie
34.2pie 34.1pie
42pie 43pie 43.0pie
44.1pie 41pie 38.7pie 58.2pie

期望的输出:

Instances of Pie:               Avg:
0.8pie 0.7pie 0.6pie            Avg pie:  0.7pie
34.2pie 34.1pie 35.8pie         Avg pie:  34.7pie
42pie 43pie 43pie               Avg pie:  42.7pie
44pie 41pie 38pie               Avg pie:  41pie
0.8pie                          Avg pie:  0.8pie
34.2pie 34.1pie                 Avg pie:  34.15pie
42pie 43pie 43.0pie             Avg pie:  42.7pie
44.1pie 41pie 38.7pie 58.2pie   Avg pie:  45.5pie

Total Average:                            30.28pie

如果每行总是有一个固定的数量,比如 2 个或者说 3 个馅饼,那么是的,我可以轻松地使用 awk print ($1+$2+$3)/3 等。但是当每行都有差异时,我会很挣扎。

我会想象使用条件语句来确定每行的数字。 IE。如果第一行有 3,则除以 3,如果第二行有 4,则除以 4,依此类推。

有人可以帮忙吗?

【问题讨论】:

  • 你试过什么?你做了什么研究? kindly assist? 我会从输入(在 sed 或 awk 中)中删除所有 pie。然后在 awk 中,我将迭代 awk 中的 foreach 字段,计算总和,然后除以 NF。看起来像一个非常非常短的 awk 脚本。
  • @KamilCuk 无需删除 pie,在将被丢弃的数字上下文中
  • @Sundeep:对不起。我没有看到我的提案计算了整个文件的平均值,我删除了 URL。
  • 请注意,平均值 (30.27) 与所有饼图的平均值 (33.47) 不同
  • 这应该不难弄清楚。试一试,如果它不适合您,请提出问题。

标签: bash awk average


【解决方案1】:

你可以使用这个awk:

awk 'function prt(s1, s2) {printf "%-40s %s\n", s1, s2} NR==1 {prt("Instances of Pie:", "Avg:")} NF {s=0; for (i=1; i<=NF; ++i) s+=$i; avg=s/NF; ++rec; sum+=avg; prt($0, "Avg pie:  " avg "pie")} !NF; END {prt("\nTotal Average:", sum/rec "pie")}' file

Instances of Pie:                        Avg:
0.8pie 0.7pie 0.6pie                     Avg pie:  0.7pie
34.2pie 34.1pie 35.8pie                  Avg pie:  34.7pie
42pie 43pie 43pie                        Avg pie:  42.6667pie
44pie 41pie 38pie                        Avg pie:  41pie
0.8pie                                   Avg pie:  0.8pie
34.2pie 34.1pie                          Avg pie:  34.15pie
42pie 43pie 43.0pie                      Avg pie:  42.6667pie
44.1pie 41pie 38.7pie 58.2pie            Avg pie:  45.5pie

Total Average:                           30.2729pie

更易读的形式:

awk '
function prt(s1, s2) {
   printf "%-40s %s\n", s1, s2
}
NR == 1 {
   prt("Instances of Pie:", "Avg:")
}
NF {
   s = 0
   for (i=1; i<=NF; ++i)
      s += $i
   avg = s/NF
   prt($0, "Avg pie:  " avg "pie")
   ++rec
   sum += avg
}
!NF
END {
   prt("\nTotal Average:", sum/rec "pie")
}' file

【讨论】:

  • 好奇你为什么不写avg = s / NF
  • 但是我喜欢OFS和column的结合
  • @glennjackman:确实我应该使用avg.= s/NF(现在已编辑)谢谢
  • 这会将 pie 转换为 pi!
  • 好的,如果你在同一行,请!NF; END... 在另一行你不需要分号。
【解决方案2】:

Perl,但它确实比 anubhava 的答案没有优势

perl -MList::Util=sum,max -lane '
      sub avg {sum(@_) / @_}
      push @lines, $_;
      push @avg, avg(@F);
  } END {
      $maxl = max map {length} @lines;
      printf "%-*s Avg:\n", $maxl, "Instances of Pie:";
      printf "%-*s Avg pie: %.1fpie\n", $maxl, $lines[$_] , $avg[$_]
          for 0..$#lines;
      printf "\n%-*s          %.2fpie\n", $maxl, "Total Average:", avg(@avg);
' pie.txt

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-12-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-06
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多