1

我对使用 awk 非常陌生,但我在 Fredrik Pihl 对这个问题的回答中找到了很多帮助,关于如何计算共享另一个字段 ($1) 的许多记录的字段平均值 ($3):

问题:如果行(特定字段)匹配,则 awk 列的平均部分

输入样本:

$cat NDVI-bm  
P01 031.RAW 0.516 0 0  
P01 021.RAW 0.449 0 0  
P02 045.RAW 0.418 0 0  
P03 062.RAW 0.570 0 0  
P03 064.RAW 0.469 0 0  
P04 083.RAW 0.636 0 0  
P04 081.RAW 0.592 0 0  
P04 082.RAW 0.605 0 0  
P04 084.RAW 0.648 0 0  
P05 093.RAW 0.748 0 0

弗雷德里克·皮尔的回答:

{
    sum[$1]+=$3
    cnt[$1]++
}


END {
    print "Name" "\t" "sum" "\t" "cnt" "\t" "avg"
    for (i in sum)
        print i "\t" sum[i] "\t" cnt[i] "\t" sum[i]/cnt[i]

}

但是,我还试图计算匹配字段的方差(每个值与平均值之间的差异平方和除以计数)。我想我可能需要一种方法来计算每个匹配记录的 END 结构之前的平均值,或者是否可以在 END 结构中进行整个方差计算,但是我需要以某种方式检索 $3 的原始值。我也不知道该怎么做。感谢您的任何提示。

4

3 回答 3

2

GNU 的代码:

{
    sum[$1]+=$3
    count[$1]++
    groups[$3]=$1
}

END {
    for (i in sum) mean[i]=sum[i]/count[i]
    for (i in groups) meandiff[i]=i-mean[groups[i]]
    for (i in groups) sumdiff2[groups[i]]+=meandiff[i]^2
    for (i in sumdiff2) var[i]=sumdiff2[i]/count[i]
    for (i in var)
        print "group:", i, "count:", count[i], "\tmean:", mean[i], "\tsum:", sum[i], "\tsumdiff^2:", sumdiff2[i], "\t\tvariance:", var[i]
}

$猫文件
P01 031.RAW 0.516 0 0
P01 021.RAW 0.449 0 0
P02 045.RAW 0.418 0 0
P03 062.RAW 0.570 0 0
P03 064.RAW 0.469 0 0
P04 083.RAW 0.636 0 0
P04 081.RAW 0.592 0 0
P04 082.RAW 0.605 0 0
P04 084.RAW 0.648 0 0
P05 093.RAW 0.748 0 0

$awk -f prog.awk 文件
组:P01 计数:2 平均值:0.4825 总和:0.965 sumdiff^2:0.0022445 方差:0.00112225
组:P02 计数:1 平均值:0.418 总和:0.418 sumdiff^2:0 方差:0
组:P03 计数:2 平均值:0.5195 总和:1.039 sumdiff^2:0.0051005 方差:0.00255025
组:P04 计数:4 平均值:0.62025 总和:2.481 sumdiff^2:0.00204875 方差:0.000512188
组:P05 计数:1 均值:0.748 总和:0.748 sumdiff^2:0 方差:0
于 2013-07-03T22:07:44.537 回答
0

您可以通过计算样本的总和和平方和来计算最后的方差。

然后

variance = (Sum of squares - (Sum*Sum)/n)/n

所以

{
    sum[$1]+=$3
    sum_squares[$1]+=$3*$3
    cnt[$1]++
}


END {
    print "Name" "\t" "sum" "\t" "cnt" "\t" "avg" "\t" "var"
    for (i in sum)
        print i "\t" sum[i] "\t" cnt[i] "\t" sum[i]/cnt[i] "\t" (sum_squares[i] - (sum[i]*sum[i])/cnt[i])/cnt[i]

}

要选择特定模式,请将其添加到求和计算的开头(注意 END 与文件末尾匹配),例如

/P03/ {
    sum[$1]+=$3
    sum_squares[$1]+=$3*$3
    cnt[$1]++
}

现在只处理其中包含 P03 的行

于 2013-07-03T17:03:24.870 回答
0

我认为在您的 awk 脚本中,如果多个原始数据在第 3 列中具有相同的值,则 groups[$3]=$1 将无法正常工作,因为这些 N 相同的值在组中只计算一次。

于 2015-12-06T09:33:56.257 回答