【问题标题】:Average of multiple files without considering missing values不考虑缺失值的多个文件的平均值
【发布时间】:2015-10-21 09:33:10
【问题描述】:

我想计算 15 个文件的平均值:- ifile1.txt、ifile2.txt、.....、ifile15.txt。每个文件的列数和行数相同。但其中一些是缺失值。部分数据看起来像

 ifile1.txt      ifile2.txt       ifile3.txt
 3  ?  ?  ? .    1  2  1  3 .    4  ?  ?  ? .
 1  ?  ?  ? .    1  ?  ?  ? .    5  ?  ?  ? .
 4  6  5  2 .    2  5  5  1 .    3  4  3  1 .
 5  5  7  1 .    0  0  1  1 .    4  3  4  0 .
 .  .  .  . .    .  .  .  . .    .  .  .  . .  

我想找一个新文件来显示这 15 个文件的平均值,而不考虑缺失值。

 ofile.txt
 2.66   2     1    3      . (i.e. average of 3 1 4, average of ? 2 ? and so on)
 2.33   ?     ?    ?      .
 3      5     4.33 1.33   .
 3      2.67  4    0.66   .
 .      .     .    .      .

这个问题类似于我之前的问题Average of multiple files in shell 脚本在哪里

awk 'FNR == 1 { nfiles++; ncols = NF }
      { for (i = 1; i < NF; i++) sum[FNR,i] += $i
       if (FNR > maxnr) maxnr = FNR
      }
      END {
      for (line = 1; line <= maxnr; line++)
      {
         for (col = 1; col < ncols; col++)
              printf "  %f", sum[line,col]/nfiles;
         printf "\n"
      }
    }' ifile*.txt

但我不能修改它。

【问题讨论】:

  • 必须是awk吗?因为我会想perl
  • 文件有多大?将它们全部保存在内存中是一种选择吗?
  • 是的,我更喜欢 awk.. 数据文件很小,有 53 列和 20000 行。

标签: linux shell unix awk average


【解决方案1】:

使用这个:

paste ifile*.txt | awk '{n=f=0; for(i=1;i<=NF;i++){if($i*1){f++;n+=$i}}; print n/f}'
  • paste 将并排显示所有文件
  • awk 计算每行的平均值:
    • n=f=0; 将变量设置为 0。
    • for(i=1;i&lt;=NF;i++) 循环遍历所有字段。
    • if($i*1) 如果字段包含数字(乘以 1 会成功)。
    • f++;n+=$i 递增 f(带数字的字段数)并求和 n
    • print n/f 计算n/f

【讨论】:

    【解决方案2】:
    awk '
       {
       for (i = 1;i <= NF;i++) {
          Sum[FNR,i]+=$i
          Count[FNR,i]+=$i!="?"
          }
       }
    END {
       for( i = 1; i <= FNR; i++){
          for( j = 1; j <= NF; j++) printf "%s ", Count[i,j] != 0 ? Sum[i,j]/Count[i,j] : "?"
          print ""
          }
       }
    ' ifile*
    

    假设文件被正确输入(没有尾随的空白行,...)

    【讨论】:

    【解决方案3】:
    awk 'FNR == 1 { nfiles++; ncols = NF }
      { for (i = 1; i < NF; i++) 
            if ( $i != "?" ) { sum[FNR,i] += $i ; count[FNR,i]++ ;}
       if (FNR > maxnr) maxnr = FNR
      }
      END {
      for (line = 1; line <= maxnr; line++)
      {
         for (col = 1; col < ncols; col++)
              if ( count[line,col] > 0 ) printf "  %f", sum[line,col]/count[line,col];
              else printf " ? " ;
         printf "\n" ;
      }
    }' ifile*.txt
    

    我只是检查'? ...

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-05-04
      • 1970-01-01
      相关资源
      最近更新 更多