#度数分布の中央値
前回作った中央値コンポーネントのJarファイルに「度数分布の中央値」コンポーネントを追加します。
「Median of frequency distribution」というらしいです。
階級に幅が無いパターンです。
#コンポーネントの仕様
- 中央値コンポーネントとほぼ同じ作り。
- レコードのフィールドは名前と値の2つをプロパティで指定します。
- 計算した中央値と名前をreadonlyプロパティへ出力します。
#作り方
IntelliJの前回作ったプロジェクトへファイルを追加します。
- com.asteria.sample.kotlin.component.MedianComponent2.kt:コンポーネント本体
- Median2.png:アイコンファイル
- Median2.html:ヘルプファイル
- ComponentDefine.xconf:Medianで作成したファイルへ追記
#コード
コードも前回作った中央値コンポーネントとほぼ同じなので、コピーします。
例によってexecuteメソッド内が処理の全てです。
- 1回レコードを回して値のフィールドから全数を取得します。
- 2回目にレコードを回して中央値を含む値を探します。
- 中央値を含むレコードの名前を取り出します。
override fun execute(p0: ExecuteContext?): Boolean {
//対象の値フィールドインデックスを取得
val targetValueFieldIndex: Int = getFieldIndex(_propValueField)
//レコードのフィールド情報取得
val record = inputConnector.stream.record
?: throw ComponentExceptionByMessageCode(this, INPUT_STREAM_IS_EMPTY)
//レコード全部読み
var allValue: Double = 0.0
do {
val fieldValue = record.getValue(targetValueFieldIndex)
if (fieldValue.isNumberType && !fieldValue.isNull) {
allValue = allValue + fieldValue.doubleValue()
}
} while (record.next())
//中央値をプロパティへ設定
val center: Double = allValue / 2
_propMedian.setValue(center.toString())
//はじめに戻る
record.first()
allValue = 0.0
do {
val fieldValue = record.getValue(targetValueFieldIndex)
if (fieldValue.isNumberType && !fieldValue.isNull) {
allValue = allValue + fieldValue.doubleValue()
if (allValue > center) {
//中央値名をプロパティへ設定
_propMedianName.setValue(record.getValue(getFieldIndex(_propNameField)).strValue())
break;
}
}
} while (record.next())
passStream();
return true
}
kotlin風のコードってどんなでしょう?なにやら違いそうな気もしますが・・・
全コードはgithubにコミットしておきました。
#ビルド
IntelliJでプロジェクトをビルドすればJarファイルの出来上がりです。
#フローで確認
出来上がったJarファイルをサーバー、デザイナーへ追加してフローを作成します。
アイコンが前回作った中央値コンポーネントに似ていますが、こっそり「2」と書いてあります。
入力レコードは3フィールドです。
- 通番
- 名前
- 個数
1番目、100円の商品が5個あります。といった感じです。
Mapperコンポーネントのマッピング内容
実行結果は、30個目を含む400円が中央値ということになりました。
#最後に
Kotlinでコンポーネントを作るのは楽です。しかし、当然ですがKotlin風にコードを書くにはKotlinに慣れる必要があり一長一短ですね。
#参考文献
中央値と最頻値