配列データの平均・分散・標準偏差
1.概要
PDH(Physical Data Hub)上やクラウドのVM(Virtual Machine)上のNode-REDで、R-MSMから送られてきたデータの平均値や標準偏差を計算する必要が発生します。送られてきたデータを配列に貯めて、その配列に入っているデータの平均値、分散、標準偏差を計算するNode-REDのフローを紹介します。
2.Node-REDのフローの説明
次に配列に格納されたデータの平均・分散・標準偏差を計算するNode-REDのフローを示します。ほぼfunctionノードで構成されています。
以下、各ノードの詳細を説明していきます。
①のLink inノードには、初期化の信号を入力して下さい。
②のfunctionノードで変数の初期化を行います。flow.lengthとflow.arrayを定義しています。flow.lengthは配列の長さです。ここでは10にしています。配列arrayに10個のデータを貯めます。
配列arrayは初期値として“0”で埋めています。
// 配列の要素数
//flow.set("length", 10);
context.flow.length = 10
// 配列作成
if (!context.flow.array) {
context.flow.array = new Array(flow.get("length"));
}
// 配列の初期化:データを0で埋める
context.flow.array.fill(0);
return msg;
③のLink inノードには、データを入力して下さい。
④のfunctionノードで配列にデータを格納します。
初めに、array.shift()を使って、配列のデータarray[0]を1つ捨てます。
その後に、array.push()を使って、配列のarray[9]にデータを1つ入れます。ここでは”rNum”となっているところを、各自の環境に合わせて変更してください。
後は、後段に送るために、msgのオブジェクト直下にarrayとlengthを置きます。
// 1bit下位にシフト
var shifted = context.flow.array.shift();
// 乱数を配列の最上位に代入
context.flow.array.push(msg.payload.rNum);
// 後段への出力準備
msg.array = context.flow.array;
msg.length = context.flow.length;
return msg;
⑤のfunctionノードで配列データの平均値を計算します。
初めに、配列の要素をすべて加算して総和sumを求めます。
その後、総和sumをデータ数msg.lengthで割って、平均値を求めます。
そして、後段に送るために、 msgのオブジェクト直下にsumとaverageを置きます。
データをシフトしていきますので、結果として移動平均になります。
// 変数設定
var sum = 0, average = 0, i;
// 配列の数値の全加算
for (i=0; i < msg.length; i++) {
sum = sum + msg.array[i];
}
// 平均値算出
average = sum / msg.length;
// 後段への出力準備
msg.sum = sum;
msg.average = average;
return msg;
⑥のfunctionノードで配列データの分散を計算します。
配列データの平均値との差の二乗和を順番に求めます。
そして、後段に送るために、 msgのオブジェクト直下にvarianceを置きます。
// 変数設定
var variance = 0, i;
// 分散計算
for (i=0; i<msg.length; i++) {
variance = variance + Math.pow(msg.array[i] - msg.average, 2);
}
variance = variance / msg.length;
// 後段への出力準備
msg.variance = variance;
return msg;
⑦のfunctionノードで配列データの標準偏差を計算します。
⑥で求めた分散値の平方根を計算します。
そして、後段に送るために、 msgのオブジェクト直下にstdを置きます。
// 変数設定
var standard_deviation = 0;
// 標準偏差計算
standard_deviation = Math.sqrt(msg.variance);
msg.std = standard_deviation;
return msg;
3.動作確認
平均・分散・標準偏差の計算のNode-REDフローの動作確認のために、データ生成のフローと計算結果のチャートのダッシュボードのフローを追加します。
データ生成回路は、0~10の乱数を1秒毎に生成して出力します。チャートのダッシュボードは、入力値(乱数)と平均値と標準偏差値を順次表示します。
3-1. 乱数データの生成
・動作確認用の乱数データは、Node-REDのfunctionノード①を使って実現しています。javascriptのMath.random()関数は、0~1までの乱数を発生する関数です。それに11を掛けて、Math.floor()関数で小数点以下を切り捨てて0~10の整数にしています。
・1秒ごとに乱数を発生させるために、delayノード②を使ってループ構成にしています。
injectノード③の繰り返し機能を使ってもよかったのですが、開始時にchartノードをクリアする機能も開始ボタンに持たせたかったので、ループを使いました。
// 0から10までの乱数を生成
var rNum = Math.floor(Math.random() * 11);
// msg.payload に格納
msg.payload = {"rNum":rNum};
return msg;
3-2.ダッシュボード(チャート)表示
・chartノードとchangeノード:
1秒毎に生成した乱数と配列の平均値と標準偏差の結果をダッシュボードのchartノードを使って可視化しています。
手前のchangeノードでmsg.rNum, msg.average, msg.stdをそれぞれ、msg.payloadに代入してチャートノードに渡してチャート化しています。
・開始時にチャートをクリア
開始のinjectボタンもしくはダッシュボードのStartボタンを押した際に、チャートをクリアするために、link outノード①からLink inノード②に信号を渡し、Clearボタンを押したのと同様の効果を実現しています。そのために、以下の2つをbuttonノードに設定します。
1) buttonノードのpayloadにjsonで”[]”(空配列)を送るように指定します③ 。
2) また、“msgが入力から届いたら、buttonをクリックされたと認識する”にチェックを入れます④。
3-3.チャートの結果
ダッシュボードのチャートの結果を結果を次に示します。