如何添加百分比列

时间:2011-11-28 22:35:05

标签: awk

我想计算所有行中每行的值百分比,并将其添加为另一列。 输入(分隔符是\ t):

1   10      
2   10
3   20
4   40

所需的输出,添加的第三列显示基于第二列中的值的计算百分比:

1   10   12.50   
2   10   12.50
3   20   25.00
4   40   50.00

我自己试图这样做,但是当我计算所有线的总数时,我不知道如何保持其余线不变。非常感谢您的帮助!

4 个答案:

答案 0 :(得分:12)

在这里,一个传递步骤awk解决方案 -

awk 'NR==FNR{a = a + $2;next} {c = ($2/a)*100;print $1,$2,c }' file file

[jaypal:~/Temp] cat file
1   10      
2   10
3   20
4   40
[jaypal:~/Temp] awk 'NR==FNR{a = a + $2;next} {c = ($2/a)*100;print $1,$2,c }' file file
1 10 12.5
2 10 12.5
3 20 25
4 40 50

更新:如果输出中需要tab,则只需将OFS变量设置为“\ t”。

[jaypal:~/Temp] awk -v OFS="\t" 'NR==FNR{a = a + $2;next} {c = ($2/a)*100;print $1,$2,c }' file file
1   10  12.5
2   10  12.5
3   20  25
4   40  50

突破模式{action}语句:

  • 第一种模式是NR==FNR。 FNR是awk的内置变量,用于跟踪给定文件中的记录数(默认情况下由新行分隔)。因此,在我们的案例中,FNR将是4.NR与FNR类似,但它不会重置为0.它继续增长。因此,在我们的案例中,NR将是8.

  • 此模式仅适用于前4个记录,这正是我们想要的。仔细阅读4条记录后,我们将总数分配给变量a。请注意,我们没有初始化它。在awk,我们没有必要。但是,如果整个第2列为0,这将会中断。因此,您可以通过在第二个操作语句中添加if语句来处理它,即仅在>时进行除法。 0否则说除以0或者其他什么。

  • next是必需的,因为我们并不想要执行第二个模式{action}语句。 next告诉awk停止进一步的操作并转到下一条记录。

  • 一旦解析了四个记录,下一个模式{action}就会开始,这非常简单。执行百分比并打印第1列和第2列以及它们旁边的百分比。

注意: 正如评论中提到的@lhf一样,只要您在文件中包含数据集,此单行内容就会起作用。如果通过管道传递数据,它将无法工作。

在评论中,讨论了如何使awk one-linerpipe而不是file获取输入。好吧,我能想到的唯一方法是将列值存储在array中,然后使用for loop将每个值与其百分比一起吐出。

arrays中的awk associative[jaypal:~/Temp] cat file 1 10 2 10 3 20 4 40 [jaypal:~/Temp] cat file | awk '{b[$1]=$2;sum=sum+$2} END{for (i in b) print i,b[i],(b[i]/sum)*100}' 2 10 12.5 3 20 25 4 40 50 1 10 12.5 并且永远不会按顺序排列,即从数组中提取值的顺序与它们输入的顺序不同。所以如果是好吧那么下面的单行应该可行。

sort

为了使它们按顺序排列,您可以将结果传递给[jaypal:~/Temp] cat file | awk '{b[$1]=$2;sum=sum+$2} END{for (i in b) print i,b[i],(b[i]/sum)*100}' | sort -n 1 10 12.5 2 10 12.5 3 20 25 4 40 50

{{1}}

答案 1 :(得分:2)

你可以通过几次传递

#!/bin/bash

total=$(awk '{total=total+$2}END{print total}' file)
awk -v total=$total '{ printf ("%s\t%s\t%.2f\n", $1, $2, ($2/total)*100)}' file

答案 2 :(得分:1)

您需要将其转义为%%。例如:

printf("%s\t%s\t%s%%\n", $1, $2, $3)

答案 3 :(得分:0)

也许有更好的方法,但我会两次传递文件。

'infile'的内容:

1       10 
2       10
3       20
4       40

'script.awk'的内容:

BEGIN {
        ## Tab as field separator.
        FS = "\t";
}

## First pass of input file. Get total from second field.
ARGIND == 1 {
        total += $2;
        next;
}

## Second pass of input file. Print each original line and percentage as third field.
{
        printf( "%s\t%2.2f\n", $0, $2 * 100 / total );
}

在我的linux框中运行脚本:

gawk -f script.awk infile infile

结果:

1       10      12.50
2       10      12.50
3       20      25.00
4       40      50.00