質問:

質問:

.txtファイル内の特定の列の中央値を計算し、その値を出力し、出力値が正常であることを確認したいと思います。初期ステップを実行して中央値を出力できますが、出力値が許容範囲内にあるかどうかはわかりません。

次のコードを含む構文エラーメッセージが表示されます。

sort -nk9 filename | awk '{a[i++]=$9;} END {x=int((i+1)/2); y=((a[x-1] + a[x])/2); z=(a[x-1]);
if ((y >= 0.5 && y <= 2) || (z >= 0.5 && z <=2));
   {if (x < (i+1)/2) 
   print "Median OR =", y "ALL OK"; 
   else print "Median OR =", z "ALL OK"}; 
else print "ERROR - OR outside range 0.5 - 2.0"}'

答え1

私の考えでは、これはあなたが望むものです。

awk '{sum+=$9;a[x++]=$9;b[$9]++}b[$9]>Mode{Mode=$9}END{print "Mean: " sum/x "\nMedian: "a[int((x-1)/2)]"\nMode: " Mode}' file

比較的きれいにまとめられています。

awk '
{
     sum+=$9
     a[x++]=$9
     b[$9]++
}
b[$9]>Mode{Mode=$9}
END{
    print "Mean: " sum/x 
    print "Median: "a[int((x-1)/2)] 
    print "Mode: " Mode
}' file

また、比較にいくつかのロジックを追加したいのですが、変数はx、y、zと呼ばれ、正しい方程式がある場合とない場合があるため、何を比較しているのか実際にはわかりません。

答え2

user78605クエリで中央値を見つける方法を案内するコードを提供していただきありがとうございます。ただし、上記のコードは、中央値を正しく計算するために必要な特定の条件を無視します。

質問:

  1. 空の末尾の行がファイルに存在する場合、それを計算すると、データサイズ、つまり平均、中央値、モード、およびその他の統計に影響を与えるため、計算しないでください。数値のない行(id est:、、"abc"など"28b")に対しても同じことを行う必要があります。"h2f"""
  2. 中央値は、元のデータセットの中間値ではなく、ソートされたデータセットの中間値です。つまり、中央値を見つけるには、まずデータをソートする必要があります。
  3. ソートされたデータセットの値の数が偶数の場合は、中央の2つの値の平均を取る必要があります。
  4. モードは周波数が最も高い値です。データセットには複数のモードを含めることができます。この場合、複数の値をモードとしてリストする必要があります。

上記の条件を考慮したコード拡張は次のとおりです。

awk -F',' '
{col=$1}{if((col ~  /^-?[0-9]*([.][0-9]+)?$/) && ($0!=""))                 
{
     sum+=col;
     a[x++]=col;
     b[col]++
     if(b[col]>hf){hf=b[col]}
}
}
END{n = asort(a);idx=int((x+1)/2)
     print "Mean: " sum/x
     print "Median: " ((idx==(x+1)/2) ? a[idx] : (a[idx]+a[idx+1])/2)
     for (i in b){if(b[i]==hf){(k=="") ? (k=i):(k=k FS i)}{FS=","}}
     print "Mode: " k
}' file

説明する:

問題#1の解決策:

col=$1#変数に保存すると、列を変更する方が簡単です。
(col ~ /^-?[0-9]*([.][0-9]+)?$/)#Stringsには、数字、ピリオド(小数点記号)、またはダッシュ(マイナス記号)のみを含めることができます。 [科学的表記法だけを無視します。 ]
($0!="")#行全体を空白にできません。

基準を満たす行に対して次のループ操作を実行します。

sum+=col# (省略形sum=sum+col.) すべての値の合計です。
a[x++]=col#各値は配列に格納されます。
b[col]++#の値はcol配列の代理キーとして扱われますb。したがって、b固有の値があるだけに多くの要素がありますcol。このイテレータは頻度数の配列を生成します。 (略語b[col]=b[col]+1。)
if(b[col]>hf){hf=b[col]}hf「最も高い周波数」を意味します。すべての周波数を繰り返し、hfより高い周波数が見つかった場合にのみ更新します。hf最初は「」(何もない)です。

問題#2の解決策:
ループ操作が完了した後:

配列に格納されている値を並べ替えます。n = asort(a)

配列の元のインデックス範囲がa「0」から「x-1」までであることは注目に値します。ソートに加えて、新しいインデックス範囲は「1」から「x」までです。そのため、中央値または中央値の平均を計算する2つの数値のうち、小さい方の数値を保持するインデックスとしてint((x+1)/2)代わりに使用しています。
int((x-1)/2)

問題#3の解決策:

((idx == (x+1)/2) ? a[idx] : (a[idx]+a[idx+1])/2)
これは if-else 構造の略称表記です。同じ
場合、値の数は奇数で、中央値はです。それ以外の場合は、最も近い整数に切り捨てられ、値の数が偶数であることを示します。この場合、合計の平均が中央値になります。int((x+1)/2)(x+1)/2a[idx]int()(x+1)/2a[idx]a[idx]+1

問題#4の解決策:

for (i in b) {if(b[i]==hf){(k=="") ? (k=i):(k=k FS i)}{FS=","}}
hfはデータセットで最も高い頻度を表す値であるため、bの値が等しい場合、代理キーはモードまたはモードの少なくともhf1つです。
このコードは、i条件に一致するすべての代理キーを連結し、それをk「Mode」という行に印刷できる変数に保存します。

追加の調整:

-Fファイル内の列区切り文字として使用される文字に基づいて調整する必要があります。

NR > 1ファイルの最初の行にヘッダーがある場合{col=$1}

FS両方の変数を結合するために使用されます。FSUse は、区切り文字を使用しないことを選択した場合に特に便利です。それは、FS=""

データ

スクリプトを作成するために、実験では以下のデータを使用した。

10
20
10
20.5
50
30
40
50
10
30
20.5


-h
h

4.35
-537
0
-0

30
d




.

結果:

Mean: -13.2281
Median: 20.25
Mode: 10,30

関連情報