はじめに

基本統計量を計算するbcコマンドのスクリプトです。

スクリプトと出力形式

【bcスクリプト】
basic_statistics.bc
define set_scale(x, s) {
    auto old_scale
    old_scale = scale
    scale = s
    x /= 1  #scale 設定
    scale = old_scale
    return (x)
}
define round(d, s) {
    auto temp;
    if(scale(d) < s) return (set_scale(d, s))
    temp = (d - set_scale(d, s)) * (10^(s+1))
    if(temp > 5) d += (1/(10^s))
    return (set_scale(d,s))
}
define power(d, i) {
    return(e(i*l(d)))
}

scale = 100
n = read()
for(i = 0; i < n; i++){
    ds[i] = read()
}
sum = 0
for(i = 0; i < n; i++){
    d = ds[i]
    sum += d
    if( i == 0) {
        max = d
        min = d
    } else {
        if(d > max){
            max = d;
        }
        if(d < min){
            min = d;
        }
    }
}
old_scale = scale
if( (n % 2) == 0) {
    scale = 0
    m1 = ds[n/2]
    m2 = ds[(n/2)+1]
    scale = old_scale
    med = (m1 + m2) / 2
} else {
    scale = 0
    med = ds[n/2]
    scale = old_scale
}
ave = sum / n
sum_dev2 = 0
sum_dev3 = 0
sum_dev4 = 0
for(i = 0; i < n; i++){
    dev = ds[i] - ave
    devs[i] = dev
    sum_dev2 += (dev * dev)
    sum_dev3 += (dev * dev * dev)
    sum_dev4 += (dev * dev * dev * dev)
}
svar = sum_dev2 / n
ssd = sqrt(svar)
uvar = sum_dev2 / (n - 1)
usd = sqrt(uvar)

skew = (n /((n -1 ) * (n - 2))) * sum_dev3 / (usd^3)
kurt = ((n * (n + 1)) /((n -1 ) * (n - 2) * (n - 3))) * (sum_dev4 / (usd^4)) - ((3 * (n - 1)^2) / ((n - 2) * (n - 3)))

print "n = "; n
print "min = "; min
print "max = "; max
print "med = "; round(med, 20)
print "ave = "; round(ave, 20)
print "sum = "; round(sum, 20)
print "svar = "; round(svar, 20)
print "uvar = "; round(uvar, 20)
print "ssd = "; round(ssd, 20)
print "usd = "; round(usd, 20)
print "skew = "; round(skew, 20)
print "kurt = "; round(kurt, 20)


【出力形式】
n = データ数
min = 最小値
max = 最大値
med = 中央値
ave = 平均値
sum = データの総和
svar = 標本分散
uvar = 不偏分散
ssd = 標本標準偏差
usd = 不偏標準偏差    
skew = 歪度
kurt = 尖度

実行例

【データファイル】
q11.txt
1
2 2 2
3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3
4 4
5

データは空白、タブ、改行で区切る。

【実行方法】
実行例
((cat q11.txt | wc -w); sort -g q11.txt) | bc -l -q basic_statistics.bc

データ数、データを空白、タブ、改行で区切って、bcにわたします。
中央値を計算する都合でデータは(数値として)ソートする必要があります。

実行結果
n = 30
min = 1
max = 5
med = 3.00000000000000000000
ave = 2.96666666666666666667
sum = 89.00000000000000000000
svar = .43222222222222222222
uvar = .44712643678160919540
ssd = .65743609744386733227
usd = .66867513545937177714
skew = .03679696392430356743
kurt = 4.50339722463221514906


環境

ホスト Windows10 COREi7
VM   VirtualBox バージョン 5.2.6 r120293 (Qt5.6.2)
     CentOS Linux release 7.4.1708 (Core)
GNU bash, バージョン 4.2.46(2)-release (x86_64-redhat-linux-gnu)
bc 1.06.95

おわりに

gawkで基本統計量を計算する」の検算用に作りました。
bcを選んだのは以下の理由によります。

  • 多倍長演算(Multiple Precision Arithmetic)をサポートしている
  • できるだけ標準的なもの(Unix/Linux)

データの読み込みにread()を使っています。bcはスクリプトの読み込みもread()も標準入力を使用しているので、shスクリプトとして作成するのが難しいです。数が少なければ環境変数で渡すのも手ですが、配列に渡すのは骨です。
以上

Sign up for free and join this conversation.
Sign Up
If you already have a Qiita account log in.