2018年10月30日火曜日

レーダーチャートの表示2

前回レーダーチャートの表示を行うことが出来たので、今回は実際の値を代入したグラフの描画を試みる。
  1. .controller('RaderChartController', ['$scope', 'Countries', function($scope, Countries) {
  2. var that = this;
  3. var itemNames = ["中性脂肪(TG)", "HDLコレステロール", "LDLコレステロール", "血糖", "HbA1c(JDS)", "GOT(AST)", "GPT(ALT)","ガンマ-GTP"];
  4. var labels = ["最新","前回","前々回"];
  5. var backgroundColors = ["rgba(153,255,51,0.4)","rgba(255,153,0,0.4)","rgba(0,153,255,0.4)"];
  6. var borderColors = ["rgba(153,255,51,1)","rgba(255,153,0,1)","rgba(0,153,255,1)"];
  7. that.ResultDataList = []
  8. Countries.get()
  9. .then(
  10. function(countries) {
  11. countries.list.forEach(function(element){
  12. that.ResultDataList.push(element);
  13. });
  14. }
  15. );
  16. $scope.tab.on('postchange', function() {
  17. //alert(JSON.stringify(that.ResultDataList[0],null,2));
  18. var i = 1;
  19. var datasets =[];
  20. that.ResultDataList.forEach(function(element){
  21. if(i<=3){
  22. var data=[0,0,0,0,0,0,0,0];
  23. element.items.forEach(function(item){
  24. var idx = itemNames.indexOf(item.itemName);
  25. if(idx>=0){
  26. //alert(idx+":"+item.itemName);
  27. data[idx] = item.value;
  28. }
  29. });
  30. // alert(JSON.stringify(data,null,2));
  31. datasets.push({
  32. 'label': labels[i-1],
  33. 'backgroundColor': backgroundColors[i-1],
  34. 'borderColor': borderColors[i-1],
  35. 'data': data
  36. });
  37. }
  38. i++;
  39. });
  40. //alert(JSON.stringify(datasets,null,2));
  41. //レーダーチャート
  42. var ctx = document.getElementById("pie-chart-area");
  43. var myChart = new Chart(ctx, {
  44. type: 'radar',
  45. data: {
  46. 'labels': itemNames,
  47. 'datasets':datasets
  48. }
  49. });
  50. });
  51. }])
3行目はレーダーチャートに表示する検査項目名のテーブルである。
4行目~6行目はレーダーチャートに描く3回分の検査のためのラベル、背景色、境界色のテーブルである。
まず、7行目で過去3回分の検査結果を格納するための配列ResultDataListの定義を行い、8行目~15行目で検査一覧を取得し、その一つ一つをResultDataListへプッシュしている。
16行目は、7~15行目の処理が非同期で行われるため、その処理が行われる前に17行目以降の処理が行われてしまうとデータがないままレーダーチャートを作成しようとするので、それを回避するため、タブがタップされた際に実行するようにする監視処理である。
その際、HTMLファイルのタブバーを定義しているons-tabbarタグに変数名 tab を定義しておく。
18行目はループ制御変数 i の定義である。これを使って過去3回分の検査を取り出す。
19行目は47行目でレーダーチャート描画関数に与えるパラメータとなるdatasetsというテーブルの定義である。
20行目はResultDataListに格納された過去の検査を一日分ずつ処理するものであり、
21行目から29行目はif文を使って過去3回分だけ該当する検査結果を取り出している。
今回表示したいレーダーチャートのデータは最新、前回、前々回の3回分であるから、繰り返す処理を先ほど定義したループ制御変数 i を用いて i が3以下のときにこの処理を繰り返すように制御している。
22行目は検査結果を格納するdataテーブルの定義をしており、レーダーチャートで扱うデータ数である8つの要素を0で初期化値している。
23~28行目はelement.items、つまり個々の検査項目に対する処理を行っている。
24行目では、当該検査項目が3行目に定義した検査項目名に一致しているかを判定するための処理を行っている。
ここで使っているindexOfというメソッドは、例えば var x = ['abc', 'def', 'ghi'] というテーブルがある場合、var idx = x.indexOf('abc') とすれば、idxの値は 0 になり、var idx = x.indeOf('ghi') とすれば idx の値は2になるといった感じで、テーブルに存在する値が何番目であるのかを返す関数である。また、テーブルに含まれていない場合は idx は-1となる。
3行目で定義している検査名テーブル itemNames に対してこのメソッドを使用することによって、item.itemNameが対象検査項目であるかどうかを判定し、25行目で idx が0以上であれば、27行目で22行目に定義した空のdataテーブルに検査値を代入している。
この様な処理を行う事で、dataテーブルに3行目に定義した検査項目名の順に検査値を設定することができる。
31行目~36行目ではこうして得られた1回分の検査情報をdatasetsテーブルにpushしている処理である。
  1. {
  2. label: 'apples',
  3. backgroundColor: "rgba(153,255,51,0.4)",
  4. borderColor: "rgba(153,255,51,1)",
  5. data: [12, 19, 3, 17, 28, 24, 7]
  6. }
上記の書式は、前回のブログで紹介したレーダーチャートのデータを記述する際の書式であるが、32行目~35行目ではこの書式に合わせて19行目で定義したdatasetsテーブルへと挿入している。
32行目のlabelは4行目のlabelsから、backgroundColorは5行目のbackgroundColorsから、borderColorは6行目のborderColorsから、
そしてdataは先ほど検査値を代入した22行目のdataからそれぞれ持ってきている。その際、配列の添え字が[i-1]となっているのは i は1から始まっているので、i のままだとテーブルの二つ目から使ってしまうことになるのでこのようにしている。
38行目で i の値に1を足し、再び21行目からの処理を i が3になるまで繰り返している。
最後にレーダーチャート描画関数に与えるパラメータを、46行目であれば3行目のitemNamesに、47行目であれば31行目のdatasetsに設定することで、
常に最新の3件のデータを表示するレーダーチャートを描画できる。
図1 レーダーチャート完成図

上図は実際に確認した結果であるが、データ通りに取得できていることが分かる。
しかし、このレーダーチャートには少々改善の余地がある。
まず、中性脂肪の値が112程度に対して、HbA1cは8.2程しかないにも拘わらず、レーダーチャートの座標のスケールが検査値の大きい検査項目に合わされているため、HbA1cは値が小さすぎて中心近くにプロットされてしまう。レーダーチャートはどの項目が突出して大きいとか小さいとかを可視化するためのものであるから、これでは、レーダーチャートにした意味がない。検査ごとに座標のスケールを変えることはできないだろうか。
また、基準値の範囲をレーダーチャート中に示すことができればより直観的に健康状態を把握できるのではないだろうか。

課題はまだまだ多く存在するが、レーダーチャートのデータ取得が行えるようになった所で本研究は一区切りとさせていただく。

0 件のコメント:

コメントを投稿

レーダーチャートの表示2

前回 レーダーチャートの表示を行うことが出来たので、今回は実際の値を代入したグラフの描画を試みる。 .controller('RaderChartController', ['$scope', 'Countries', funct...