计算文本文件中列的平均值

时间:2013-06-03 18:09:05

标签: awk

我有两个名为f1和f2的文件夹。这些文件夹包含300个文本文件,包含2列。文件内容如下所示。我想计算第二列的平均值。两个文件夹中的文件名相同。

file1 in f1 folder
54  6
55 10
57 5

file2 in f1 folder
24  8
28  12

file1 in f2 folder
34 3
22 8

file2 in f2 folder
24  8
28  13

输出

                   folder1       folder2

     file1         21/3= 7       11/2=5.5
     file2         20/2=10       21/2=10.5

      --            --             --    

      --            --             --

    file300         --             --

              total mean of folder1 = sum of the means/3oo
              total mean of folder2 = sum of the means/3oo

2 个答案:

答案 0 :(得分:2)

我用两个awk脚本来做。 (最初,我在中间有一个sort阶段,但这实际上并不是必需的。但是,我认为两个脚本可能比尝试将它们合并为一个更容易。如果其他人这样做,那么全部都在一个'并且它是可理解的,然后选择他们的解决方案。)

样本运行和输出

这是基于问题中显示的4个文件。命令行中列出了文件的名称,但顺序无关紧要。该代码假定文件名中只有一个斜杠,文件名中没有空格等。

$ awk -f summary1.awk f?/* | awk -f summary2.awk
file1                      21/3   =      7.000       11/2   =      5.500
file2                      20/2   =     10.000       21/2   =     10.500
total mean of f1     =     17/2   =      8.500
total mean of f2     =     16/2   =      8.000

summary1.awk

function print_data(file, sum, count) {
    sub("/", " ", file);
    print file, sum, count;
}
oldfile != FILENAME { if (count > 0) { print_data(oldfile, sum, count); }
                      count = 0; sum = 0; oldfile = FILENAME
                    }
                    { count++; sum += $2 }
END                 { print_data(oldfile, sum, count) }

依次处理每个文件,对第2列中的值求和并计算行数。它打印出文件夹名称,文件名,总和和计数。

summary2.awk

    {
        sum[$2,$1] = $3
        cnt[$2,$1] = $4
        if (file[$2]++ == 0) file_list[n1++] = $2
        if (fold[$1]++ == 0) fold_list[n2++] = $1
    }
END {   for (i = 0; i < n1; i++)
        { 
            printf("%-20s", file_list[i])
            name = file_list[i]
            for (j = 0; j < n2; j++)
            {
                folder = fold_list[j]
                s = sum[name,folder]
                n = cnt[name,folder]
                a = (s + 0.0) / n
                printf("   %6d/%-3d = %10.3f", s, n, a)
                gsum[folder] += a
            }
            printf("\n")
        }
        for (i = 0; i < n2; i++)
        {
            folder = fold_list[i]
            s = gsum[folder]
            n = n1;
            a = (s + 0.0) / n
            printf("total mean of %-6s = %6d/%-3d = %10.3f\n", folder, s, n, a)
        }
    }

file关联数组跟踪对文件名的引用。 file_list数组按文件名的顺序保存文件名。同样,fold关联数组跟踪文件夹名称,fold_list数组按照它们出现的顺序跟踪文件夹名称。如果您使用为第一个命令提供名称的顺序执行了一些奇怪的操作,则可能需要在两个sort命令之间插入awk命令,例如sort -k2,2 -k1,1。< / p>

sum关联数组包含给定文件名和文件夹名的总和。 cnt关联数组包含给定文件名和文件夹名的计数。

报告的END部分有两个主循环(尽管第一个循环包含嵌套循环)。第一个主循环按所示顺序处理文件,生成一行,每行包含一个条目。它还会累积文件夹名称的平均值。 第二个主循环生成每个文件夹的“总平均值”数据。我不确定统计数据是否有意义(不应该将folder1的总体平均值作为folder1中值的总和除以条目数,或者41/5 = 8.2而不是17/2或8.5?),但计算完成了我认为问题的要求(平均值/文件数量,在问题中写成300)。

答案 1 :(得分:0)

在grep的帮助下:

grep '[0-9]' folder[12]/* | awk '
    {
       split($0,b,":"); 
       f=b[1]; split(f,c,"/"); d=c[1]; f=c[2]; 
       s[f][d]+=$2; n[f][d]++; nn[d]++;} 
    END{ 
      for (f in s) {
        printf("%-10s", f);
        for (d in s[f]) {
          a=s[f][d] / n[f][d];
          printf(" %6.2f ", a);
          p[d] += a;
        }
        printf("\n");
      }  
      for (d in p) { 
        printf("total mean %-8s = %8.2f\n", d, p[d]/nn[d]);
      }
    }'