awkを使用して比率を計算する

awkを使用して比率を計算する
awk 'NR==1{$4="ratio"}NR>1{$4 = ($3)/($2)} {print $1 "\t" $2 "\t" $3 "\t" $4}' A  B

awk:コマンド。行:1:(FILENAME = A FNR = 18)致命的:0で除算しようとしました。

このエラーを解決するのに役立つ人がいますか?

NR==1ここで合計はどういうNR>1意味ですか?それは奇妙な例です。わかりません。 NRがレコード番号であることはわかりますが、ここではなぜ使用しますか?

答え1

作成者の例では、ファイルAとBを次の形式で想像しているようです。

ファイルA:

X Y Z
1 2 3
4 5 6

ファイルB:

6 7 8
o o 0

AWKの例では、4番目の列を生成します。ここで、NRは現在AWKによって処理されている行を表します。最初の行では、4番目の引数を文字列「ratio」(列名)に設定し、後続のすべての行では、4番目の引数を2番目の引数で割った3番目の引数に設定します。結果:

awk 'NR==1{$4="ratio"}NR>1{$4 = ($3)/($2)} {print $1 "\t" $2 "\t" $3 "\t" $4}' A
X   Y   Z   ratio
1   2   3   1.5
4   5   6   1.2
6   7   8   1.14286
1   2   3   1.5

発生したエラーは次のとおりです。

awk:コマンド。行:1:(FILENAME = A FNR = 18)致命的:0で除算しようとしました。

ファイルAの18行目に2列と3列の数字が含まれていることを確認してください。

sedを使用して 'o'文字を0に変換できます。

cat A B | sed 's/\bo\b/0/g'

列 2 が 0 であることを確認し、それに応じてアクションを取ることができます。

awk 'NR==1{$4="ratio"}NR>1{if($2==0) $4 = "N/A"; else $4 = ($3)/($2)}

まとめると、次のような利点が得られます。

cat A B | sed 's/\bo\b/0/g' | awk 'NR==1{$4="ratio"}NR>1{if($2==0) $4 = "N/A"; else $4 = ($3)/($2)} {print $1 "\t" $2 "\t" $3 "\t" $4}'
X   Y   Z   ratio
1   2   3   1.5
4   5   6   1.2
6   7   8   1.14286
0   0   0   N/A

答え2

与えられた例では、

awk 'NR==1{$4="ratio"}NR>1{$4 = ($3)/($2)} {print $1 "\t" $2 "\t" $3 "\t" $4}' A  B

NRこれまでに読み込んだレコード数です。次の例では、これを使用して次のようにテーブルヘッダーをスキップできます。

Date        Cost     Quantity
2016/04/10  12.57    3
2016/04/19  11.74    2

なぜなら、「コスト」を「数量」(数字ではない)に分割できないからです。

ところで、あなたのデータできる4つ以上の列があります。ただし、awkを使用すると、入力データにない列に割り当てることができます。したがって、最初は$4="ratio"既存の列を変更することも可能ですが、連続レコードの計算を反映するためにデータに列を追加する可能性があります。

エラー(0で割る)の解釈は別の質問ですNR。数値データがあることを確認し、$2パターン$3を使用できます。たとえば、次の確認を追加します。

次のようなものを生産します

#!/bin/sh
awk 'function isnum(v) { 
     if ( v ~ /^[0-9.]+$/ ) 
         return 1; 
     else 
         return 0; 
     } 
     (NR==1){$4="ratio"} 
     (NR>1 && NF >= 3 && isnum($2) && isnum($3) && $3 > 0){$4 = ($3)/($2)} 
     {print $1 "\t" $2 "\t" $3 "\t" $4}' A  B

このisnum関数は単純化されていますが、符号なしの素数を受け入れます。

1行のスクリプトを好む場合は、awkスクリプトが自由形式であることを覚えておいてください。だから...これを行うことができます:

awk 'function isnum(v){if(v~/^[0-9.]+$/)return 1;else return 0;}(NR==1){$4="ratio"}(NR>1&&NF>=3&&isnum($2)&&isnum($3)&&$3>0){$4=($3)/($2)}{print $1"\t"$2"\t"$3"\t"$4}' A  B

関連情報