• 締切済み

データの系列の平均の求め方のアルゴリズム

100個の数値が並んでいてその平均を求めるという場合、全部足して100で割る、ということしか考えられなかったのですが、そうではないアルゴリズムがあるようです。プログラム的な説明だと以下のようです。 ave=0.0 平均が分かっていると仮定する。 do i=1,100 xx=x(i)-ave あるデータx(i)と、分かっている思っている平均aveとの差をとる。 ave=ave+xx/i その差をそこまでのデータ個数iで割る。新しいデータによる平均の変化量とみてそれを前の平均に加える。 enddo それを十分大きな回数繰り返す。そうすると平均に近づく。 このような考え方はある学問分野では常識なのかもしれませんが、近似ということになると思います。データの数が十分大きくて最初の平均が実際と異なるエラーが相対的に減ってくるとかです。このアルゴリズムにはどのような制約が付くものでしょうか。例えば乱数を発生させてその平均を求めるときに全部発生させてから和を取って個数で割るのではなく、1つ1つ乱数を発生させて発生し終わった時点で平均が計算できてしまっている、ということになります。分散も同じようなアルゴリズムになると思います。実験や理論的な検討を加えることはできると思いますが、あまりにも簡単なので常識であり、かつ性質も調べられているのではないかと思ってお尋ねしました。いかがでしょうか。

みんなの回答

  • OKWavex
  • ベストアンサー率22% (1222/5383)
回答No.2

99個の平均は以下の通り a99 = x1+x2+x3+・・・+x99)/99 100個の平均は以下の通り a100 =(x1+x2+x3+・・・+x99+x100)/100 = (x1+x2+x3+・・・+x99+x100)/99 ×99/100 = ( (x1+x2+x3+・・・+x99)/99+x100/99 ) ×99/100 = ( a99 + x100/99 ) ×99/100 = a99 ×99/100 + x100/100 = a99×(100-1)/100 +x100/100 = a99 - a99/100 + x100/100 = a99 + (x100-a99)/100 これは近似式ではありません すなわち > xx=x(i)-ave あるデータx(i)と、分かっている思っている平均aveとの差をとる。 > ave=ave+xx/i その差をそこまでのデータ個数iで割る。新しいデータによる > 平均の変化量とみてそれを前の平均に加える。 は正しい平均値の計算方法であり近似式ではありませんので個数が増えるごとにその範囲での正しい平均を計算しています

skmsk1941093
質問者

お礼

考えてみるとほんとにそうですね。過去をすべて記録しておく必要があると思っていました。これだと過去のデータを保存しておく必要がありませんね。気が付きませんでした。

  • f272
  • ベストアンサー率46% (8012/17126)
回答No.1

0個の平均は0ですからave[0]=0 (n-1)個までの平均ave[n-1]がわかっていれば,それにn個目のx[n]を加えた平均ave[n]は ave[n]=(ave[n-1]*(n-1)+x[n])/n で求められます。式を変形すると ave[n]=ave[n-1]+(x[n]-ave[n-1])/n ですね。 つまり,あなたの書いたアルゴリズムは正確に平均を求めているのであって,近似ではありません。もちろん数値計算ですから丸目誤差などはあるでしょうが,そういうものを除けば全く正確です。

skmsk1941093
質問者

お礼

なるほど、考えてみると確かにそうですね。過去をメモリに収める必要はないということが分かりました。非常にシンプルなのに気づきませんでした。

関連するQ&A

  • アルゴリズムとデータの個数

    各種配列アルゴリズムのデータ個数と処理時間による比較を行って、このとき,処理時間の平均値を用いたのですが、整列一歩手前等,特別な条件下では処理時間が入れ替わることがありそれはどのようなアルゴリズムの場合かおしえてくれませんか?

  • (Excel)データの個数の平均が知りたい

    下記のような時系列的に並んでいる時間データが有ります。 00:00 00:00 00:00 00:01 00:01 00:01 00:01 00:02 00:02 00:03 00:03 00:03 実際には、各時間に約30個ずつあり(時間データによって個数が異なる)全部で約3万ものデータがあります。 各データの個数、個数の平均や範囲を示す方法はありませんか? 量が膨大でグラフにするとぐちゃぐちゃになってしまいます。 上手く伝えられなくてすみません。

  • 何番目に作成されたのかを表示させる方法

    ある範囲内で整数を複数個、適当につくり、その整数の平均値を取った後、適当に作った整数と最も近い平均値が何番目に作成されたのかを表示させるという問題についての質問です。 とりあえず1から100までの整数、その数10個にして、 #include <stdio.h> #include <stdlib.h> #include <time.h> int main() { int a[9]; int ave; time_t t; int i; int sum; srand(time(&t)); for(i = 0; i < 10; i++){ a[i] = rand() % 100; printf("ransu%d\n", a[i]); } ave += a[i] / 10; printf("ave%d\n", ave); return 0; } と、すればとりあえず乱数10個は生成されたのですが、何故かaveの値が合いません。 あと、この生成された乱数とaveの絶対値の差が最も小さいもの=最も平均値と生成された乱数の値が近い、と言うプログラムを書けば良いのだと思うのですが、その場合、どの様な式を使えば導き出せるのか、教えて頂ければ幸いです。 よろしくお願いいたします。

  • 配列の乱数と平均値、個数表示

    0から9までの整数乱数を100個発生させ、100個の乱数の平均値も合わせて出力し、0から9それぞれの個数を数えるための変数に必ず配列を用いるプログラムを下記に作成したんですけども、出現個数カウント用の変数を10個用意していけないという条件で出現個数カウント用の配列を用意し、 結果が、 7 7 1 7 3 9 1 2 5 0 0 3 6 8 4 9 1 4 2 4 8 2 4 2 6 0 9 3 5 8 6 6 6 2 0 9 5 2 6 9 5 0 5 3 9 2 6 7 0 6 1 4 1 1 1 9 7 0 5 0 6 9 7 4 9 9 7 5 3 6 1 9 6 6 6 7 1 2 6 1 4 9 1 3 1 3 7 0 0 8 1 9 3 2 9 4 4 5 4 0 0 *********** 11 1 ************* 13 2 ********* 9 3 ******** 8 4 ********** 10 5 ******** 8 6 ************** 14 7 ********* 9 8 **** 4 9 ************** 14 平均 4.4 に表示されるプログラムがわかりません、Java初心者なので作ったプログラムのどこを直せばいいのか教えてください。 class Kadai06_5 { public static void main(String args[]) { int n=10; int a[] = new int[n]; int i; int sum=0; double avg=0; for(i=0; i<100; i++){ System.out.print((int)(Math.random()*10)); sum +=(int)(Math.random()*10); } for(i=0; i<n; i++){ System.out.println(); } avg=(double)sum/100; System.out.println("平均"+avg); } }

    • ベストアンサー
    • Java
  • エクセル2002で、増減のあるデータの平均値を取る

    エクセル2002を使っています。 画像のように、D127からD136までに数値データが入ります。 画像のデータはふたつですが、1個から10個の範囲で他セルを参照した結果が入ります。 ご覧の通りやりたいことは個体差データを合計し、個数で割り平均値を取りたいと思います。 平均だけならもちろん出来るのですが、その数の増減が有る場合の関数はどのようなものになるでしょうか? 詳しい方、よろしくお願いいたします。

  • 確率変数の平均と分散

    平均μ、分散σ^2の確率変数Xについて、その平方根SQRT(X)の平均と分散を求めるにはどうすればよいでしょうか。求め方も含めて教えてください。(確率変数の和,差,積,商の平均,分散についてはWEB上に多くの資料があるのですが、平方根については見つけることができませんでした)よろしくお願いします。 ohkawaさん、ozuさん、コメントを有難うございました。 E[x^0.5]=E[((x-μ)+μ)^0.5]=E[μ^0.5(1+(x-μ)/μ)^0.5]とおき、(1+(x-μ)/μ)^0.5を二項展開し、(x-μ)^3/μ^3以上の高次の項を微小量として無視して展開すると次のようになりました。 E[x^0.5]=μ^0.5-σ^2/8/μ^1.5 これを使って分散は次のようになりました。 V[x^0.5]=σ^2/4/μ+3σ^4/64/μ^3 エクセルの乱数で確認すると近似値としてはいい線いっているようです。 平均,分散の右辺第二項を無視するとohkawaさんの答えに一致します。 分散の結果が間違っていました。 V[x^0.5]=σ^2/4/μ-σ^4/64/μ^3 です。

  • 任意の標準偏差で正規分布の乱数を発生させたい

    2次元の正規分布の乱数を発生させたいんですが、 調べたところ、 平均0、分散1の正規分布の乱数の発生方法アルゴリズムが以下のものになることがわかりました。 「Box-Maller法:区間(0,1)の2個の一様乱数x1,x2と2個の量y1,y2との間の変換 y1=sqrt(-2*ln(x1))*cos(2*Pi*x2) y2=sqrt(-2*ln(x1))*sin(2*Pi*x2)」 ここで、平均0、分散0.2の正規分布の乱数を発生させたいのですが、どうすればよいでしょうか? 単純にy1,y2に0.2を掛けるだけでもできますが、これは数学的に正しいのでしょうか?

  • 配列変数を用いて平均値を求める

    こんにちわ 実は、入力データを使って平均値を求めるプログラムについてなんですけど。 //データの平均値の計算 #include <stdio.h> void main () { int i, k, n, x[100]; double a; while (1) { a = 0; printf("データ数を入力してください..."); scanf("%d",&n); printf("正の実数のデータを入力してください。"); for (i = 0;i < n ;i++) scanf("%d",&x[i]); for (k = 0;k < n;k++) a += x[k]; printf("平均値 %f\n", a/n); } } すいません、インデントがいい加減です。  こうやると普通に平均値を出せますが、最初にデータ数を入力しなければいけません。  私は、データの個数を入力しないで平均値を出したいと思います。どういう風に上のプログラムを変更すればできるのでしょうか?上のプログラムに誤植があるとは思いますが。。。  また、たとえば最後に0以下の数字を入力したらデータ入力を終わらせる...  if(x[i]<=0)break; はどこに入れればいいでしょうか?  たくさんの質問すいません。ご教授よろしくお願いします。

  • N個の整数の並び替えるアルゴリズム

    N個の整数1,2,3,...Nから任意のM個(M < N )を取り出すのですが、重複はダメという場合、どのようなアルゴリズムがあるでしょうか。重複ありなら、Nまでの一様乱数を発生させて整数化して取り出すことは可能です。今回は重複なしです。重複があったらやり直して重複なしになるまでやり続けるというのはダメだなと思っています。 データ処理言語のRはコマンド1つのようですが。言語はFortranなのですが、アルゴリズムのレベルだとどれでも同じと考えています。よろしくお願いします。

  • 過去のデータから、未来を予測する手法について

    (数学で良いかわかりませんが、よろしくお願いします) よく、過去のデータから未来の値を予測(想定)すること があるかと思います。 例えば、過去の5年のデータ(これをx1,x2,x3,x4,x5とする)から、来年の値(x6)を想定するということです。 x6を求める手法について教えてください。 一般的なのは、最小二乗法等で1次近似してx6を求めたり なんて感じです。 他にも2次近似とか、3次近似とか、1次近似でも 重みをつけたり、ただ単に5つの平均にしたり 重みつきで平均にしたりと・・・・。 どんなデータの時にどんなものを使ったらよいのですか? ところで、1次近似したとします。 x=a×□+b で表したとします x6の値として、「ただ単に□に6を入れたとき」というのと □に5を入れたときをx5'、6を入れたときをx6'とします。 x6として、x5+(x6'-x5')とすることがあると思います。 (つまり、傾きだけ求めて、x5に傾きの分だけ加える。) これって、信憑性ありますか? 駄文ですみません。