awk
計算に使用できますか?平均各行(各行には異なる列があります)次のファイルがあります。最初の列は名前です。各行の平均を計算し、入力ファイルの最後の列に結果を印刷したいと思います。
入力ファイル( data1.csv
):
EMPLOYEE1,0.395314,0.384513,,
EMPLOYEE2,5.4908,5.2921,,
EMPLOYEE3,0.0002323,0.00022945,0.00023238,0.00022931
EMPLOYEE4,0.00335516,0.00328432,0.00340309,0.00327163
EMPLOYEE5,1.4816,1.4367,1.4854,1.4353
EMPLOYEE6,7.89E-06,7.93E-06,7.95E-06,7.87E-06
EMPLOYEE7,3.724E-06,3.8745E-06,3.9428E-06,3.7227E-06
EMPLOYEE8,0.699498,0.688892,0.704256,0.683486
EMPLOYEE9,33.5195,31.9736,33.6779,31.742
希望の出力:
EMPLOYEE1,0.395314,0.384513,,,0.3899135
EMPLOYEE2,5.4908,5.2921,,,5.39145
EMPLOYEE3,0.0002323,0.00022945,0.00023238,0.00022931,0.00023086
EMPLOYEE4,0.00335516,0.00328432,0.00340309,0.00327163,0.00332855
EMPLOYEE5,1.4816,1.4367,1.4854,1.4353,1.45975
EMPLOYEE6,7.89E-06,7.93E-06,7.95E-06,7.87E-06,7.91E-06
EMPLOYEE7,3.72E-06,3.87E-06,3.94E-06,3.72E-06,3.82E-06
EMPLOYEE8,0.699498,0.688892,0.704256,0.683486,0.694033
EMPLOYEE9,33.5195,31.9736,33.6779,31.742,32.7282
以下を試しましたが、 awk
列が最大NFより小さい行の平均を計算しません。
awk -F',' '{ s = 0; for (i = 2; i <= NF; i++) s += $i; print $1, (NF > 1) ? s / (NF - 1) : 0; }' data1.csv
そして
awk -F',' '{sum=0; for (i=2;i<=NF;i++)sum+=$i; print $0,sum/(NF-1)}' data1.csv
しかし、私のコードはNF行を変更しません。各行のNFを変更して、希望の出力を得ることはできますか?
答え1
1つの方法は次のとおりです。
$ awk -F',' -v OFS=',' '{
s=0;
numFields=0;
for(i=2; i<=NF;i++){
if(length($i)){
s+=$i;
numFields++
}
}
print $0, (numFields ? s/numFields : 0)}' data1.csv
EMPLOYEE1,0.395314,0.384513,,,0.389914
EMPLOYEE2,5.4908,5.2921,,,5.39145
EMPLOYEE3,0.0002323,0.00022945,0.00023238,0.00022931,0.00023086
EMPLOYEE4,0.00335516,0.00328432,0.00340309,0.00327163,0.00332855
EMPLOYEE5,1.4816,1.4367,1.4854,1.4353,1.45975
EMPLOYEE6,7.89E-06,7.93E-06,7.95E-06,7.87E-06,7.91e-06
EMPLOYEE7,3.724E-06,3.8745E-06,3.9428E-06,3.7227E-06,3.816e-06
EMPLOYEE8,0.699498,0.688892,0.704256,0.683486,0.694033
EMPLOYEE9,33.5195,31.9736,33.6779,31.742,32.7282
0.389914
awkによって印刷された結果は、最初の0.779827/2
行の平均では0.389914
なくなることを意味します0.389915
。これは、awkが最も近い偶数に丸められ、デフォルトの印刷モード(変数によって制御されますOFMT
)があるためです%0.6g
。さらに精度が必要な場合は、次のことができます。
$ awk -F',' -v OFS=',' -v OFMT='%0.7g' '{
s=0;
numFields=0;
for(i=2; i<=NF;i++){
if(length($i)){
s+=$i;
numFields++
}
}
print $0, (numFields ? s/numFields : 0)}' data1.csv
EMPLOYEE1,0.395314,0.384513,,,0.3899135
EMPLOYEE2,5.4908,5.2921,,,5.39145
EMPLOYEE3,0.0002323,0.00022945,0.00023238,0.00022931,0.00023086
EMPLOYEE4,0.00335516,0.00328432,0.00340309,0.00327163,0.00332855
EMPLOYEE5,1.4816,1.4367,1.4854,1.4353,1.45975
EMPLOYEE6,7.89E-06,7.93E-06,7.95E-06,7.87E-06,7.91e-06
EMPLOYEE7,3.724E-06,3.8745E-06,3.9428E-06,3.7227E-06,3.816e-06
EMPLOYEE8,0.699498,0.688892,0.704256,0.683486,0.694033
EMPLOYEE9,33.5195,31.9736,33.6779,31.742,32.72825