我想分别计算第8列中以1.000,1.35,1.70,......(递增0.35)......,120(每行14行)的行之间的最大值,然后计算使用Awk它们之间的平均值(即最大值)。非常感谢您的帮助
1.000 8 .... 0.017947838827838864
1.000 8 .... 0.029306373626373672
1.000 8 .... 0.018125164835164853
...
...
1.350 27 ... 0.0014171428571428946
1.350 27 ... 0.0017828571428571971
1.350 27 ... 0.0017828571428571971
...
...
120.000 28 ... 0.49277503924646787
120.000 28 ... 0.41021689560439561
120.000 29 ... 0.38946329670329682
答案 0 :(得分:0)
为了测试,假设以下输入文件:
1.000 8 0.017947838827838864
1.000 8 0.029306373626373672
1.000 8 0.018125164835164853
1.350 27 0.0014171428571428946
1.350 27 0.0017828571428571971
1.350 27 0.0017828571428571971
120.000 28 0.49277503924646787
120.000 28 0.41021689560439561
120.000 29 0.38946329670329682
使用以下awk文件:
BEGIN { initialize(); }
NF==3 { processline($1,$3);}
END { printmax(); printavg(); }
function initialize()
{
lastselector=-1
count=0
sum=0
}
function processline(selector,value)
{
if(selector!=lastselector) {
if(lastselector!=-1) {
printmax()
}
lastselector=selector
max=value
}
else {
if(value>max) {
max=value
}
}
}
function printmax()
{
print "selector=" lastselector " max=" max
sum=sum+max
count=count+1
}
function printavg()
{
avg=sum/count
print "avgmax=" avg
}
结果是:
awk -f test.awk test.dat
selector=1.000 max=0.029306373626373672
selector=1.350 max=0.0017828571428571971
selector=120.000 max=0.49277503924646787
avgmax=0.174621
要适应您的问题,请将$ 3修改为$ 8(或您想要的任何列),并将NF = test设置为文件中预期的列总数。 (此模式只是为了排除不包含数据的其他行)未能设置该权限将导致不处理任何行并且除以零错误。此代码假定您的输入具有按行组合在一起的第1列的所有相同值。
希望这会有所帮助。顺便说一句,你的例子已经足够了。
答案 1 :(得分:0)
<强>输入强>
$ cat file
1.000 8 0.017947838827838864
1.000 8 0.029306373626373672
1.000 8 0.018125164835164853
1.350 27 0.0014171428571428946
1.350 27 0.0017828571428571971
1.350 27 0.0017828571428571971
120.000 28 0.49277503924646787
120.000 28 0.41021689560439561
120.000 29 0.38946329670329682
<强>输出强>
$ awk 'FNR==NR{A[$1] = $3 > A[$1] ? $3 : A[$1]; next }$1 in A{ print "selector = " $1 " max = "A[$1];sum+=A[$1]; c++; delete A[$1] }END{print "Average = ", sum/c}' file file
selector = 1.000 max = 0.029306373626373672
selector = 1.350 max = 0.0017828571428571971
selector = 120.000 max = 0.49277503924646787
Average = 0.174621
更易读的版本:
awk 'FNR==NR{
# If filed3 ($3) is greater than array A element where index being field1,
# then A[$1] = $3, otherwise array A value will not change
A[$1] = $3 > A[$1] ? $3 : A[$1]
# Stop processing go to next line
next
}
# Here we read same file once again
# if index key $1 exists in array A
$1 in A{
# print field1 and max value
print "selector = " $1 " max = "A[$1]
# sum of max
sum+=A[$1]
# Count
c++
# Delete element of array
delete A[$1]
}
END{
# Print Average finally
print "Average = ", sum/c
}
' file file
其他方式 - 在END块处理,如果输出顺序无关紧要
awk '{
A[$1] = $3 > A[$1] ? $3 : A[$1]
}
END{
for(i in A)
{
print "selector = " i " max = "A[i]
sum+=A[i]
}
print "Average = ", sum/length(A)
}
' file
答案 2 :(得分:0)
这真的不是很难。由于示例数据中只有三个有用的列,因此我在下面的代码中将8更改为3:
awk '$1 != col1 { if (col1 != "") max[col1] = max3; max3 = $3; col1 = $1 }
{ if ($3 > max3) max3 = $3 }
END { if (col1 != "") max[col1] = max3;
for (i in max) { sum += max[i]; num++ }
if (num > 0) print sum / num
}'
第一行处理第1列中的更改。如果第1列之前有值(col1
),则将最大值(max3
)保存在索引的数组max
中按col1
。同时重置col1
的当前值,并将最大值设置为$3
中的当前值。
下一行是'每一行'处理;如果第3列中的值大于先前的最大值,则记录新的最大值。
END
块处理'第1列中的更改',与第一个块一样。它不需要重置值,因为没有更多的输入行。下一行计算值的总和。如果要处理的值至少为1,则最后一行打印平均值。
根据样本数据,它会产生答案:
0.174621
显然,对于包含8列的数据,您需要将所有三个星形映射到八个。
此代码假定数据在第1列中分组,因此相关条目在一起。有可能避免这种假设,如:
awk '{ if (!$1 in max) max[$1] = $3;
if ($3 > max[$1]) max[$1] = $3 }
END {
for (i in max) { sum += max[i]; num++ }
if (num > 0) print sum / num
}'
这实际上比以前的版本更简单;它只是查看$3
(或您的版本中的$8
)中的值是否大于与$1
关联的最大值,如果是,则存储它。如果之前没有看到$1
,则将最大值设置为当前值;这避免了“最大值的安全价值是什么 - 值是否为负值”的问题。
在这两种解决方案中,如果您希望打印最大值,可以在END
块中轻松执行此操作,例如:
for (i in max) print i, max[i]
或者您可以使用更适合您的华丽打印格式。请注意,键(i
值)的显示顺序是不确定的。如果订单很重要,您必须在awk
或单独的sort
流程中对值进行排序。