5011


  * file1とfile2のA列の平均値
  * file1とfile2のB列の平均値

をシェルスクリプトで比較するためには、どのような方法がありますでしょうか。  
CSVのフォーマットは、下記のようになります。

[code]

    A,B
    28960,0.072569
    28960,0.072569
    31856,0.078464
    34752,0.072569
    37648,0.072569
    43440,0.072569
    46336,0.072569
    49232,0.072569
    55024,0.072569
    60816,0.072569
    63712,0.072569
    66608,0.072569
    69504,0.072569
    72400,0.072569
    75296,0.072569
    78192,0.078464
    86880,0.072569
    89776,0.072569
    92672,0.072569
    95568,0.078464
    110048,0.072569
    112944,0.072569
    115840,
    121632,
    124528,0.072569
    127424,0.072569
    133216,0.072569
    139008,0.072569
    144800,0.072569
    144800,0.072569
    153488,
    156384,
    165072,
    188240,
    191136,
    196928,0.078464
    202720,
    
[/code]


CC BY-SA 3.0
2015-01-21T04:00:35.197
4953
2015-02-18T08:16:41.090
2015-02-18T08:16:41.090
7590
7590
question
macos sh
2つのCSVファイル内の値の平均値を比較をするには


これってtshark云々関係なくて、単純にcsv fileに書いてある値の平均値をsh scriptで求めたいだけですよね？  
そしたら、出力したcsvのformatが分かればなんとでもなると思います。  
まずは、実際に出力したcsvを抜粋して載せたら良いんじゃないでしょうか？

* * *

コメントして放置するのもなんなんで、bashで作ってみました。

とりあえず、以下のsh scriptを作って、実行権与えてあげる。ファイル名を『csvAve.sh』とかにしたとして`./csvAve.sh
file1.csv file2.csv`ってやるとそれぞれの平均出します。

[code]

    #!/bin/bash
    
    IFS=$','
    BC=/usr/bin/bc
    
    function getAve(){
      sum0=0
      sum1=0
      cnt0=0
      cnt1=0
    
      while read line; do
        col=(`echo "${line}"`)
    
        if [ -n "${col[0]}" ]
        then
          sum0=`echo "${col[0]} + ${sum0}" | ${BC}`
          cnt0=`echo "${cnt0} + 1" | ${BC}`
        fi
    
        if [ -n "${col[1]}" ]
        then
          sum1=`echo "${col[1]} + ${sum1}" | ${BC}`
          cnt1=`echo "${cnt1} + 1" | ${BC}`
        fi
      done < $1
    
      ave0=`echo "${sum0} / ${cnt0}" | ${BC}`
      ave1=`echo "scale=8; ${sum1} / ${cnt1}" | ${BC}`
      echo ${ave0}, ${ave1}
    }
    
    sum=0
    for path in "$@"; do
      ave=(`getAve ${path}`)
      sum=`echo "${ave[1]} + ${sum}" | ${BC} `
      echo "${path}: ${ave[0]} ${ave[1]}"
    done
    
    echo "ave: `echo "scale=8; ${sum} / $#" | ${BC}`"
    
[/code]

1行目のheader行無視する処理無いのは相変わらずですが...少し直してみました。  
A,Bそれぞれの平均を出して、全ファイルのBの平均を出します。  
B列が欠測しててもA列有効にしちゃってますけど、良いのかな？

> data1.csv: 102585 .07345325  
>  data2.csv: 100968 .07338210  
>  ave: .07341767


CC BY-SA 3.0
2015-01-21T04:22:56.850
4957
2015-01-21T12:07:55.970
2015-01-21T12:07:55.970
2383
2383
4953
answer


半分ネタです。

sh スクリプトでということですが、素の sh や bash では実数が扱えないので、ksh あるいは zsh
が必要です。スクリプトは次のような実装になります:

[code]

    #!/bin/ksh
    
    set -u
    
    calc() {
      typeset -lE ws ws_sum irtt irtt_sum
      typeset ws_n=0
      typeset irtt_n=0
    
      read
      while IFS=, read ws irtt; do
        if  [[ -n $ws ]]; then
          let ws_sum+=ws
          let ws_n++
        fi
        if [[ -n $irtt ]];then
          let irtt_sum+=irtt
          let irtt_n++
        fi
      done
    
      printf '%.4f,%.4f\n' "$((ws_sum / ws_n))" "$((irtt_sum / irtt_n))"
    }
    
    for csv_name in "$@"; do
      echo "$csv_name,$(calc <"$csv_name")"
    done
    
[/code]

これを `calc.ksh` として、入力が `a.csv`、`b.csv`、`c.csv` というファイルにあるなら、次のように実行します。

[code]

    $ ./calc.ksh a.csv b.csv c.csv
    a.csv,94305.6410,0.0508
    b.csv,92672.0000,0.0514
    c.csv,91118.0488,0.0519
    
[/code]

ピュアシェルで書きましたが、awk などを利用したほうが速いでしょうね。


CC BY-SA 3.0
2015-01-21T05:24:11.650
4962
2015-01-21T05:36:58.003
2015-01-21T05:36:58.003
3061
3061
4953
answer


シェルスクリプトであればやはり古典的にawkだろう、ということで。フィールドが増えても対応出来ます。

[code]

    #! /bin/sh
    
    FILES="nanoha.csv fate.csv"
    for f in $FILES; do
      tmpfile=`mktemp -t csv`
      tmpfiles=($tmpfiles $tmpfile)
      trap "rm -f $tmpfile" SIGHUP SIGINT SIGQUIT SIGTERM
    
      awk -F, '
        NR == 1 {
          ncols = NF;
          for(i = 0; i < NF; i++) {
            cols[i] = $(i + 1)
          }
        }
    
        1 < NR {
          nrows++;
          for(i = 0; i < ncols; i++) {
            sum[i] += $(i + 1)
          }
        }
    
        END {
          for(i = 0; i < ncols; i++) {
            print cols[i] " " sum[i]/nrows;
          }
        }
      ' < $f | sort > $tmpfile
    done
    
    echo FILE $FILES
    join -a 1 -a 2 ${tmpfiles[@]}
    
[/code]

出力 (データは適当な物を使っています):

[code]

    FILE nanoha.csv fate.csv
    A 4.75 1.75
    B 5 8
    
[/code]


CC BY-SA 3.0
2015-01-21T14:09:25.067
5011
2015-01-21T14:09:25.067
76
4953
answer


zsh/ksh や bc, awk
で処理する方法が回答で出されていますので、[jq](http://stedolan.github.io/jq/)(v1.4) を使ってみました。

[code]

    $ cat input.dat | jq -s -r -R '
        def average(v): map(.[v] | select(.!=null) | tonumber) | add / length;
        split("\n") |
        [(.[0] | split(",") | map("Average of "+.+" = ")),
         (.[1:] | map(split(",")) |
           [(average(0)|tostring), (average(1)|tostring)])] |
        (map(.[0]) | join("")), (map(.[1]) | join(""))'
    =>
    Average of A = 100968.64864864865
    Average of B = 0.07338210344827589
    
[/code]

こんな方法もあるという事で、ご参考までにどうぞ。


CC BY-SA 3.0
2015-01-21T23:58:29.483
5021
2015-01-21T23:58:29.483
4953
answer