2018年7月5日木曜日

MONACAサンプルアプリの編集4

今回は、グラフの描画部分のプログラミングを行う。具体的には、指定した国、年の人口を取得するPopulationサービスを書き換えて、OpenDolphinから指定した検査項目の検査結果を検査履歴から取得する処理を行う。
nv.addGraph(function() {
    chart = nv.models.stackedAreaChart()
    .useInteractiveGuideline(true)
    .showControls(false)
    .margin({left: 50, right: 30});
上記のコードはNVD3を用いたグラフ描画の方法なのだが、これを以下のコードに書き換える
nv.addGraph(function() {
    chart = nv.models.lineChart()
    .useInteractiveGuideline(true)
    .showControls(false)
    .margin({left: 50, right: 30});
2行目の「chart = nv.models.lineChart()」という記述を用いることで折れ線グラフの描画を行う事が出来る。しかし、この状態でアプリケーションを実行すると、エラーが表示され、グラフの描画を行う事が出来ない。3~5行目の.から始まる記述はメソッドを示しているのだが、いずれかのメソッドがlineChartのメソッドではないものが記述されている為、エラーが表示されてしまう。ここで、一つ一つのメソッドに対してコメントアウトを行い、どのメソッドがlineChartのものではないのか検証したところ、4行目の「.showControls(false)」といったメソッド(グループモードと積み上げモードを切り替える)がlineChartのメソッドではなかったので、このメソッドをコメントアウトしたところ、折れ線グラフでの描画を行う事が出来た。

次に、グラフのx軸に示されている日時が適切な形式になっていないため、変換を行う必要がある。
chart.xAxis
  .tickFormat(d3.format(',r'));
この「chart.xAxis」というものは、グラフのx軸を示しているものである。2行目の「.tickFormat」というものは目盛の形式を示しており、(,r)のrは数字という意味であり、カンマは数字に3桁ごとにカンマを付与するといったものである。
これを、以下の書式に書き換える。
chart.xAxis
  .tickFormat(
    function(d) {
      return d3.time.format('%Y-%m-%d')(new Date(d));
    }
  );
上記のxAxisのtickFormatメソッドは、変数dを通じて渡されてきた座標目盛りの値を、無名関数を使って任意の形式に編集している。ここでは基準日時からの経過秒が格納されている数値変数dをnew Date(d)によってJavascriptの日付オブジェクトに変換し、それをd3.time.format関数を使って書式'%Y-%m-%d'により「YYYY-MM-DD」の形式に編集している。
図1 x軸の目盛りを日付にしたグラフ画面
これよにり、上記図1のようにx軸に日付を表示することができた。
次に、y軸の値に単位を追加する処理を行う。
chart.yAxis
  .tickFormat(function(d) {
    if ((d / 1000000) >= 1) {
      d = Math.round(d / 100000) / 10 + 'M';
    }
    else if ((d / 1000) >= 1) {
      d = Math.round(d / 100) / 10 + 'K';
    }
    return d;
  });
これは1,000,000や、1,000等の値の大きい数をそれぞれ、MやKの単位をつけて短くするものであるが、今回扱うデータはあまり大きい値ではないので、この部分をコメントアウトする。
chart.yAxis
  .tickFormat(function(d) {
   /* if ((d / 1000000) >= 1) {
      d = Math.round(d / 100000) / 10 + 'M';
    }
    else if ((d / 1000) >= 1) {
      d = Math.round(d / 100) / 10 + 'K';
    }*/
    return d + scope.data[0].unit;
  });
9行目の「d + scope.data[0].unit;」という記述でグラフのy軸の数値に検査単位を付与することが出来る。ここで、scope.dataは、PopulationChartディレクティブのビューであるHTML中のpopulation-chartタグに付与されたdata属性を表している(下記)。
<population-chart ng-if="country.showChart" data="country.population"></population-chart>
このcountry.populationにはPopulationサービスで作成した検査項目の時系列データが配列として格納されており、その直近の検査日の結果scope.data[0]の検査単位であるscope.data[0].unitを使用してy軸の目盛りに単位をつけている。

現状のグラフでは、正常値の上限値と下限値がy軸の最大値と最小値になってしまい、基準値の範囲がわかりくい状況である。そこで、y軸の範囲(最大値と最小値)を広げることにした。尚、検査項目ごとに基準値の値は異なるので、基準値の上限値や下限値に定数を加えたり引いたりしてy軸の最大値や最小値を設定するのは適切ではない。したがって、y軸の最大値を「基準値の上限値 + 上限値と下限値の差」、最大値を「下限値 - 上限値と下限値の差」とすることにした。そのために、lineChartのyDomainメソッドに以下のように目盛りの範囲を設定した。
.yDomain([2 * lower-upper, 2 * upper-lower])
ここで、「lower」は基準値の下限、「upper」は基準値の上限である。
このように座標軸の最小・最大を設定するにはyDomainメソッドを使用する。
次に、基準値の下限「lower」と上限「upper」をscope.dataから求める。
var normalValue =  scope.data[0].normalValue.split(/-/);
var lower = parseFloat(normalValue[0]);
var upper = parseFloat(normalValue[1]);
直近の検査項目の情報はscope.data[0]に入っているので、そこから基準値scope.data[0].normalValueを取り出し、それを区切り文字「-」で分割し、先頭要素を下限値、2番目の要素を上限値として実数に変換する。これにより、下記の図2の様にグラフのy軸の最大値と最小値の設定を行う事ができ、正常値範囲がわかりやすくなった。

図2 基準値範囲を見やすくしたグラフ画面
ただし,図2をよく見ると,縦軸の最大値と最小値の値が計算誤差のせいで「・・・9999」と歯切れの悪い数値になっているので,編集する必要がある。

0 件のコメント:

コメントを投稿

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

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