正しくない出力を表示するawkスクリプト


8

awkスクリプトの問題に直面しています-データファイルの各課題の最低、最高、平均のスコアを含むレポートを生成する必要があります。割り当ての名前はにありcolumn 3ます。

入力データは次のとおりです。

Student,Catehory,Assignment,Score,Possible
Chelsey,Homework,H01,90,100
Chelsey,Homework,H02,89,100
Chelsey,Homework,H03,77,100
Chelsey,Homework,H04,80,100
Chelsey,Homework,H05,82,100
Chelsey,Homework,H06,84,100
Chelsey,Homework,H07,86,100
Chelsey,Lab,L01,91,100
Chelsey,Lab,L02,100,100
Chelsey,Lab,L03,100,100
Chelsey,Lab,L04,100,100
Chelsey,Lab,L05,96,100
Chelsey,Lab,L06,80,100
Chelsey,Lab,L07,81,100
Chelsey,Quiz,Q01,100,100
Chelsey,Quiz,Q02,100,100
Chelsey,Quiz,Q03,98,100
Chelsey,Quiz,Q04,93,100
Chelsey,Quiz,Q05,99,100
Chelsey,Quiz,Q06,88,100
Chelsey,Quiz,Q07,100,100
Chelsey,Final,FINAL,82,100
Chelsey,Survey,WS,5,5
Sam,Homework,H01,19,100
Sam,Homework,H02,82,100
Sam,Homework,H03,95,100
Sam,Homework,H04,46,100
Sam,Homework,H05,82,100
Sam,Homework,H06,97,100
Sam,Homework,H07,52,100
Sam,Lab,L01,41,100
Sam,Lab,L02,85,100
Sam,Lab,L03,99,100
Sam,Lab,L04,99,100
Sam,Lab,L05,0,100
Sam,Lab,L06,0,100
Sam,Lab,L07,0,100
Sam,Quiz,Q01,91,100
Sam,Quiz,Q02,85,100
Sam,Quiz,Q03,33,100
Sam,Quiz,Q04,64,100
Sam,Quiz,Q05,54,100
Sam,Quiz,Q06,95,100
Sam,Quiz,Q07,68,100
Sam,Final,FINAL,58,100
Sam,Survey,WS,5,5
Andrew,Homework,H01,25,100
Andrew,Homework,H02,47,100
Andrew,Homework,H03,85,100
Andrew,Homework,H04,65,100
Andrew,Homework,H05,54,100
Andrew,Homework,H06,58,100
Andrew,Homework,H07,52,100
Andrew,Lab,L01,87,100
Andrew,Lab,L02,45,100
Andrew,Lab,L03,92,100
Andrew,Lab,L04,48,100
Andrew,Lab,L05,42,100
Andrew,Lab,L06,99,100
Andrew,Lab,L07,86,100
Andrew,Quiz,Q01,25,100
Andrew,Quiz,Q02,84,100
Andrew,Quiz,Q03,59,100
Andrew,Quiz,Q04,93,100
Andrew,Quiz,Q05,85,100
Andrew,Quiz,Q06,94,100
Andrew,Quiz,Q07,58,100
Andrew,Final,FINAL,99,100
Andrew,Survey,WS,5,5
Ava,Homework,H01,55,100
Ava,Homework,H02,95,100
Ava,Homework,H03,84,100
Ava,Homework,H04,74,100
Ava,Homework,H05,95,100
Ava,Homework,H06,84,100
Ava,Homework,H07,55,100
Ava,Lab,L01,66,100
Ava,Lab,L02,77,100
Ava,Lab,L03,88,100
Ava,Lab,L04,99,100
Ava,Lab,L05,55,100
Ava,Lab,L06,66,100
Ava,Lab,L07,77,100
Ava,Quiz,Q01,88,100
Ava,Quiz,Q02,99,100
Ava,Quiz,Q03,44,100
Ava,Quiz,Q04,55,100
Ava,Quiz,Q05,66,100
Ava,Quiz,Q06,77,100
Ava,Quiz,Q07,88,100
Ava,Final,FINAL,99,100
Ava,Survey,WS,5,5
Shane,Homework,H01,50,100
Shane,Homework,H02,60,100
Shane,Homework,H03,70,100
Shane,Homework,H04,60,100
Shane,Homework,H05,70,100
Shane,Homework,H06,80,100
Shane,Homework,H07,90,100
Shane,Lab,L01,90,100
Shane,Lab,L02,0,100
Shane,Lab,L03,100,100
Shane,Lab,L04,50,100
Shane,Lab,L05,40,100
Shane,Lab,L06,60,100
Shane,Lab,L07,80,100
Shane,Quiz,Q01,70,100
Shane,Quiz,Q02,90,100
Shane,Quiz,Q03,100,100
Shane,Quiz,Q04,100,100
Shane,Quiz,Q05,80,100
Shane,Quiz,Q06,80,100
Shane,Quiz,Q07,80,100
Shane,Final,FINAL,90,100
Shane,Survey,WS,5,5

awkスクリプト

BEGIN {
  FS=" *\\, *"
}

FNR>1 {
  min[$3]=(!($3 in min) || min[$3]> $4 )? $4 : min[$3]
  max[$3]=(max[$3]> $4)? max[$3] : $4
  cnt[$3]++
  sum[$3]+=$4
}
END {
  print "Name\tLow\tHigh\tAverage"
  for (i in cnt)
    printf("%s\t%d\t%d\t%.1f\n", i, min[i], max[i], sum[i]/cnt[i])

}

予想されるサンプル出力:

Name    Low     High    Average
Q06     77      95      86.80
L05     40      96      46.60
WS      5       5       5
Q07     58      100     78.80
L06     60      99      61
L07     77      86      64.80

スクリプトを実行すると、すべての割り当てで「低​​」の0が返されますが、これは正しくありません。どこがいけないの?ご案内ください。


ここにサンプルデータとスクリプトを表示します。
karakfa

入力のサンプルと予想される出力の画像またはリンクの投稿は控え、質問にコードタグ付きのテキストとして投稿して、その旨をお知らせください。
RavinderSingh13

別のユーザーによって既に編集されています。
pikaraider、

GNU awkを使用すると、投稿されたコードから、datamashの回答と同じ結果が得られます。あなたはうまくいきます。
Shawn

@Shawn、上記で投稿したawkスクリプトが期待どおりに機能しているということですか?実行すると、すべての割り当てで「低​​」の0が表示されます。間違いを修正できるように、正しい出力を生成するawkコードを共有していただけませんか?
pikaraider

回答:


1

あなたは確かにawkでこれを行うことができますが、このスクリプトにもタグを付けたので、私は他のツールがオプションであることを想定しています。データ内に存在するグループに関するこの種の統計の収集では、GNU datamashは多くの場合、ジョブを単純な1行に削減します。例えば:

$ (echo Name,Low,High,Average; datamash --header-in -s -t, -g3 min 4 max 4 mean 4  < input.csv) | tr , '\t'
Name    Low     High    Average
FINAL   58      99      85.6
H01     19      90      47.8
H02     47      95      74.6
H03     70      95      82.2
H04     46      80      65
H05     54      95      76.6
H06     58      97      80.6
H07     52      90      67
L01     41      91      75
L02     0       100     61.4
L03     88      100     95.8
L04     48      100     79.2
L05     0       96      46.6
L06     0       99      61
L07     0       86      64.8
Q01     25      100     74.8
Q02     84      100     91.6
Q03     33      100     66.8
Q04     55      100     81
Q05     54      99      76.8
Q06     77      95      86.8
Q07     58      100     78.8
WS      5       5       5

これは、ヘッダー()を持つ単純なCSV入力()の3番目の列(-g3に加え-sて、入力(ツールの要件)をソートするために同じ値)を持つ各グループについて、最小値、最大値、および平均値を表示することを示しています4列目。すべてに新しいヘッダーが与えられ、カンマをタブに変換するためにパイプされます。-t,--header-intr


1

あなたのコードはそのままGNU awkで動作します。ただし、-t移植性のない構成について警告するオプションを指定して実行すると、次のようになります。

awk: foo.awk:6: warning: old awk does not support the keyword `in' except after `for'
awk: foo.awk:2: warning: old awk does not support regexps as value of `FS'

また、awkの別の実装(mawk私の場合)でスクリプトを実行すると、Low列に0が表示されます。したがって、スクリプトにいくつかの調整を加えます。

BEGIN {
  FS=","
}

FNR>1 {
  min[$3]=(cnt[$3] == 0 || min[$3]> $4 )? $4 : min[$3]
  max[$3]=(max[$3]> $4)? max[$3] : $4
  cnt[$3]++
  sum[$3]+=$4
}
END {
  print "Name\tLow\tHigh\tAverage"
  PROCINFO["sorted_in"] = "@ind_str_asc" # gawk-ism for pretty output; ignored on other awks
  for (i in cnt)
    printf("%s\t%d\t%d\t%.1f\n", i, min[i], max[i], sum[i]/cnt[i])

}

他のawkでも期待どおりに機能します。

変更:

  • 正規表現の代わりに単純なカンマをフィールド区切りとして使用します。
  • cnt[$3]が0に等しいかどうかを確認することによってこの割り当てが初めて確認されたときに、条件付きの最小値を現在の値に変更します(その値は後の行でインクリメントされるため、初めてになります)。現在の最小値はこの値より大きいです。

@Shawnに感謝します。完璧に動作します!
pikaraider

または、コンピューターにインストールされていると仮定して、gawk代わりに実行してGNUバージョンを取得します。
Shawn

1

別の同様のアプローチ

$ awk -F, 'NR==1 {print "name","low","high","average"; next} 
                 {k=$3; sum[k]+=$4; count[k]++}
     !(k in min) {min[k]=max[k]=$4} 
       min[k]>$4 {min[k]=$4} 
       max[k]<$4 {max[k]=$4}                    
       END       {for(k in min) print k,min[k],max[k],sum[k]/count[k]}' file | 
 column -t

name   low  high  average
Q06    77   95    86.8
L05    0    96    46.6
WS     5    5     5
Q07    58   100   78.8
L06    0    99    61
L07    0    86    64.8
H01    19   90    47.8
H02    47   95    74.6
H03    70   95    82.2
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.