none
単純移動平均のライブラリを探しています RRS feed

  • 質問

  • テキストボックスに、単純移動平均の計算結果を出したいと思います。

    単純移動平均のライブラリが在りそうで、見つからないので困っています。

    http://msdn.microsoft.com/ja-jp/library/dd456706.aspx

      ↑ ここに、それらしい物がありますが、チャート表示は要りません。因みに、動かそうと思ったら動きませんでした。

    何か良い方法を知りませんか?

    以上、よろしくお願いします。

    2011年6月7日 9:06

回答

  • こんにちは。

    私もライブラリ探すより作った方が早いと思います。

    例) ※例外とか考えてない
        /// <summary>
        /// 単純移動平均(最初から対象インデックスまでの平均を求める)
        /// </summary>
        /// <param name="actuals">実績</param>
        /// <param name="targetIndex">対象インデックス</param>
        /// <returns></returns>
        static decimal CalcSMA(IEnumerable<decimal> actuals, int targetIndex)
        {
          return actuals.Take(targetIndex + 1).Average();
        }
    
    
        /// <summary>
        /// 単純移動平均(期間を指定して平均を求める)
        /// </summary>
        /// <param name="actuals">実績</param>
        /// <param name="startIndex">開始インデックス</param>
        /// <param name="endIndex">終了インデックス</param>
        /// <returns></returns>
        static decimal CalcSMA(IEnumerable<decimal> actuals, int startIndex, int endIndex)
        {
          return actuals.Skip(startIndex).Take(endIndex - startIndex + 1).Average();
        }
    
    • 回答としてマーク taokato 2011年6月8日 0:23
    • 回答としてマークされていない taokato 2011年6月8日 0:47
    • 回答としてマーク taokato 2011年6月8日 4:28
    2011年6月7日 10:27
  • わざわざリングバッファとか考えなくてもSystem.Collections.Generic.Queue<>つかえばいいのでは?
    受信したらキューにいれて必要点数たまったら計算して捨てていくだけですし。

    System.Collections.Generic.Queue<double> que = new Queue<double>(10);
    foreach (double value in values)
    {
      que.Enqueue(value); //受信したときにEnqueue
      if(que.Count>=10)
      {
        System.Diagnostics.Debug.WriteLine(que.Average()); //平均出すだけ
        que.Dequeue(); //あふれたのを捨てる
      }
    }
    
    • 回答としてマーク taokato 2011年6月8日 0:23
    • 回答としてマークされていない taokato 2011年6月8日 0:47
    • 回答としてマーク taokato 2011年6月8日 4:27
    2011年6月7日 11:44
  • valuesは受信した数値が入っているIEnumerable<>です。

    移動平均はたとえば10点平均だと1点目から10点目、2点目から11点目、3点目から12点目のように、それぞれで平均を出すことですよね?
    ならば2~11を計算するときは1点目は要らないから捨てていいのです。

    あらかじめ全てのデータがそろっている状態から移動平均を出すなら

    var q= from index in Enumerable.Range(0, values.Count - 10+1) select values.Skip(index).Take(10).Average();
    
    で一発で済みます。。
    ですが、受信データを受信毎に処理するならば、Queueに入れておいて都度計算の手法を採用することになると思います。

     

    • 回答としてマーク taokato 2011年6月8日 4:27
    2011年6月8日 3:39

すべての返信

  • 単純移動平均であればライブラリを使わなくても簡単に実装できると思いますが、何か特殊な仕様でもあるのでしょうか? 例えば20日単純移動平均であれば20日分を足して20で割るだけですよね??

     


    ★良い回答には回答済みマークを付けよう! わんくま同盟 MVP - Visual C# http://d.hatena.ne.jp/trapemiya/
    2011年6月7日 9:35
    モデレータ
  • 言葉足らずで済みません。

    計測機械から(シリアルポートより)送られてくるデータを、移動平均させたいと思います。

    したがって、リングバッファ(FIFO)を作って、移動平均をさせる段取りになると思います。

     

    以上、よろしくお願いします。

    2011年6月7日 10:22
  • こんにちは。

    私もライブラリ探すより作った方が早いと思います。

    例) ※例外とか考えてない
        /// <summary>
        /// 単純移動平均(最初から対象インデックスまでの平均を求める)
        /// </summary>
        /// <param name="actuals">実績</param>
        /// <param name="targetIndex">対象インデックス</param>
        /// <returns></returns>
        static decimal CalcSMA(IEnumerable<decimal> actuals, int targetIndex)
        {
          return actuals.Take(targetIndex + 1).Average();
        }
    
    
        /// <summary>
        /// 単純移動平均(期間を指定して平均を求める)
        /// </summary>
        /// <param name="actuals">実績</param>
        /// <param name="startIndex">開始インデックス</param>
        /// <param name="endIndex">終了インデックス</param>
        /// <returns></returns>
        static decimal CalcSMA(IEnumerable<decimal> actuals, int startIndex, int endIndex)
        {
          return actuals.Skip(startIndex).Take(endIndex - startIndex + 1).Average();
        }
    
    • 回答としてマーク taokato 2011年6月8日 0:23
    • 回答としてマークされていない taokato 2011年6月8日 0:47
    • 回答としてマーク taokato 2011年6月8日 4:28
    2011年6月7日 10:27
  • わざわざリングバッファとか考えなくてもSystem.Collections.Generic.Queue<>つかえばいいのでは?
    受信したらキューにいれて必要点数たまったら計算して捨てていくだけですし。

    System.Collections.Generic.Queue<double> que = new Queue<double>(10);
    foreach (double value in values)
    {
      que.Enqueue(value); //受信したときにEnqueue
      if(que.Count>=10)
      {
        System.Diagnostics.Debug.WriteLine(que.Average()); //平均出すだけ
        que.Dequeue(); //あふれたのを捨てる
      }
    }
    
    • 回答としてマーク taokato 2011年6月8日 0:23
    • 回答としてマークされていない taokato 2011年6月8日 0:47
    • 回答としてマーク taokato 2011年6月8日 4:27
    2011年6月7日 11:44
  • Tetsuaki Uchida さん

    こんにちは

    Average関数があることさえ知らなかった。 (爆)

    参考にさせて頂きます。

    2011年6月7日 23:45
  • gekka さん

    有難うございます。

    今まで、FIFOのキーワードを探していたので見つかりませんでした。

    Queueの存在があるとは、知りませんでした。 (^^;

    参考にさせて頂きます。

    処で、「values」は、「que」の事ですよね?

    それと、移動平均をしますので平均値を出すごとにアドレスを+1させますよね。

    あふれたのを捨てる」のでは、移動平均にならないのではないでしょうか?

     

    不躾と思われるでしょうが、よろしくお願いします。

    2011年6月8日 0:21
  • valuesは受信した数値が入っているIEnumerable<>です。

    移動平均はたとえば10点平均だと1点目から10点目、2点目から11点目、3点目から12点目のように、それぞれで平均を出すことですよね?
    ならば2~11を計算するときは1点目は要らないから捨てていいのです。

    あらかじめ全てのデータがそろっている状態から移動平均を出すなら

    var q= from index in Enumerable.Range(0, values.Count - 10+1) select values.Skip(index).Take(10).Average();
    
    で一発で済みます。。
    ですが、受信データを受信毎に処理するならば、Queueに入れておいて都度計算の手法を採用することになると思います。

     

    • 回答としてマーク taokato 2011年6月8日 4:27
    2011年6月8日 3:39