본문 바로가기

Study/ETC

[개발]예측 데이터 그래프(Dygraph)

예측 데이터 그래프 (Dygraph)

말은 예측 데이터 그래프지만 실제로는 이차 방정식 그래프에 마커 표시를 한것이다.

시설물의 균열은 시간이 지나면서 점점 벌어지는데 오랜 시간 측정한 데이터로 다음 균열의 진행 시기를 예측 할 수 있다고 한다.

CodePen 바로가기

 

Source Code

  • bigdata.html
<!DOCTYPE html> <html lang="en">  <head>     <meta charset="UTF-8">     <meta name="viewport" content="width=device-width, initial-scale=1.0">     <meta http-equiv="X-UA-Compatible" content="ie=edge">     <title>Document</title>     <link rel="stylesheet" href="http://dygraphs.com/dist/dygraph.css">     <script src="./jquery-3.3.1.js"></script>     <script src="http://dygraphs.com/dist/dygraph.js"></script>     <script src="./moment.js"></script>     <script src="./numbro.min.js"></script>     <script src="./bridgeGraph.js"></script> </head>  <body>     <p>시작일 <input type="date" id="startDate" value="2019-01-01"></p>      <p>끝일 <input type="date" id="endDate" value="2035-01-01"></p>     <p>색상 <input type="color" id="color" rgba></p>     <p>이벤트 포인트</p>     <p>         <input type="checkbox" name="dots" value="0.2" id="dottwo" checked> <label for="dottwo">0.2</label>         <input type="checkbox" name="dots" value="0.3" id="dotthree" checked> <label for="dotthree">0.3</label>          <input type="checkbox" name="dots" value="0.5" id="dotfive" checked> <label for="dotfive">0.5</label>          <input type="checkbox" name="dots" value="0.7" id="dotseven"> <label for="dotseven">0.7</label>          <input type="checkbox" name="dots" value="0.9" id="dotnine"> <label for="dotnine">0.9</label>      </p>     <button id="generateBtn" onclick="graphOptionGenerate()">조회</button>      <div id="graph_div" style="width:1024px; height:400px;"></div>     <div id="record"></div> </body>  </html> 
  • bigdata.js
var data = {     "returnCode": "200",     "data": {         "paramA": 3.647711896363213e-18,         "paramB": -1.1277236853945568e-8,         "paramC": 8.762329392601957,         "currentPoint": {             "evetId": "",             "x": 1.546835815E9,             "y": 0.0461795755014478         },         "stdPoint": null,         "eventPoints": [{             "evetId": "D20181127204455070000004",             "x": 1.751149584e+9,             "y": 0.2         }, {             "evetId": "D20181127204610688000005",             "x": 1.809584815e+9,             "y": 0.3         }, {             "evetId": "D20181127204842488000007",             "x": 1.898518878e+9,             "y": 0.5         }]     } }  var bigDataGraph;  const hexToRgb = function(hex) {     var result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);     return result ? [parseInt(result[1], 16), parseInt(result[2], 16),parseInt(result[3], 16)] : null; }   const axisTickFormatter = function (type, format) {     if (type == "timeseries") {         return function (d) {             return moment(d).format(format)         };     } else if (type == "indexed") {         return function (d) {             return numbro(d).format(format)         };     } }  const timeFormatter = function (time, format) {     return moment(time * 1000).format(format); }  const quadraticEquationequation = function (x, a, b, c) {     let y = (a * Math.pow(x, 2)) + (b * x) + c;     return parseFloat(y); }  const quadraticFormula = function (y, a, b, c_param) {     let c = c_param - y;     let x = (-1 * b + Math.sqrt(b * b - 4 * a * c)) / (2 * a);     return x; }  const bigdataGenerate = function (el, option, suboption) {     console.log(suboption)     if (option.returnCode == 204) {         document.getElementById("el").innerHTML("빅데이터 값이 존재하지 않습니다.");         return;     } else {         var a = parseFloat(option.data.paramA);         var b = parseFloat(option.data.paramB);         var c = parseFloat(option.data.paramC);          var graph = document.getElementById(el);         var width = parseInt(graph.style.width);         var x1 = suboption.startDate;         var x2 = suboption.endDate;         var xs = 1.0 * (x2 - x1) / width;          var data = [];         for (var i = 0; i < width; i++) {             var x = parseFloat(x1 + i * xs);             var y = quadraticEquationequation(x / 1000, a, b, c);              var row = [x];             if (y.length > 0) {                 for (var j = 0; j < y.length; j++) {                     row.push(y[j]);                 }             } else {                 row.push(y);             }             data.push(row);         }     }         var labels = ['Time'];     if (data[0].length == 2) {         labels.push('Y');     } else {         for (var i = 1; i < data[0].length; i++) {             labels.push('Y' + (1 + i));         }     }      return new Dygraph(graph, data, {         labels: labels,         axisLabelFontSize: 11,         displayAnnotations: true,         axes: {             x: {                 valueFormatter: axisTickFormatter("timeseries", "YYYY/MM/DD"),                 axisLabelFormatter: axisTickFormatter("timeseries", "YYYY/MM/DD"),             },             y: {                 valueFormatter: axisTickFormatter("indexed", {                     "mantissa": 4,                     "thousandSeparated": true                 }),                 axisLabelFormatter: axisTickFormatter("indexed", {                     "mantissa": 4,                     "thousandSeparated": true                 }),             }         },         underlayCallback: function (canvas, area, g) {             var size = suboption.dotsVal.length;             let recordData = [];             suboption.dotsVal.forEach(function (el, index) {                 var bottom_left = g.toDomCoords(quadraticFormula(el, a, b, c) * 1000 - 15768000000, 0);                 var top_right = g.toDomCoords(quadraticFormula(el, a, b, c) * 1000 + 15768000000, 0);                 var left = bottom_left[0];                 var right = top_right[0];                 var opacify = 1 / size * (index + 1)                 canvas.fillStyle = "rgba(" + suboption.color[0] + "," + suboption.color[1] + "," + suboption.color[2] + ", " + opacify + ")";                 canvas.fillRect(left, area.y, right - left, area.h);                 recordData[index] = {point : el, time : timeFormatter(quadraticFormula(el, a, b, c), "YYYY/MM/DD")}             })             recordGenerate(recordData)           },         colors: ["#000000"],     }); }  const recordGenerate = function(r_data){     let html = ""     r_data.forEach(function(el, idx){         html += "<p>"+el.point+": "+el.time+"</p>"     })     $("#record").html(html) }  window.onload = function () {     graphOptionGenerate(data) }  const graphOptionGenerate = function (param) {     let startDate = "";     let endDate = "";     let color = "";     let dotsVal = []      if (param == undefined) {         startDate = new Date(document.getElementById("startDate").value).getTime()         endDate = new Date(document.getElementById("endDate").value).getTime()         color = hexToRgb(document.getElementById("color").value)         let dotsList = Array.from($("input[name=dots]:checked"))         dotsList.forEach(function (el, index) {             dotsVal[index] = $(el).val() * 1.0;         })     } else {         startDate = param.data.currentPoint.x * 1000         endDate = 2208988800000         color = hexToRgb("#2dbcb3")         dotsVal = [0.2, 0.3, 0.5]     }     let suboption = {         startDate,         endDate,         color,         dotsVal,     };      bigDataGraph = bigdataGenerate("graph_div", data, suboption) } 

 

Usage

1. Setup

<link rel="stylesheet" href="http://dygraphs.com/dist/dygraph.css">  <script src="./jquery-3.3.1.js"></script> <script src="http://dygraphs.com/dist/dygraph.js"></script> <script src="./moment.js"></script> <script src="./numbro.min.js"></script> 

 

data 가 서버로부터 받은 값이고 사용자의 옵션에 따라 여러가지 항목을 정할 수 있게 하였다.

처음에는 디폴트 옵션이 적용되고 옵션 설정시 해당 옵션 적용

  • 서버로 부터 받는 값
    • 시작일 (현재 값)
    • 계수 (ParamA, ParamB, ParamC)
    • 이벤트 포인트
  • 사용자 옵션 값
    • 시작일, 종료일
    • 그래프 bar 색상 (bar)
    • 이벤트 포인트

 

주요 함수

  • bigdataGenerate(el, option, suboption)suboption : 사용자 옵션
  • 실제 그래프를 그려 Dygraph 객체를 반환하는 함수
  • el : 그래프를 그릴 elementid option : 서버로 부터 받은 data
  • quadraticEquationequation(x, a, b, c)넘겨 받은 값으로 y를 반환함
  •  
  • x, a, b, c : 이차 방정식 계수 및 x
  • quadraticFormula(y, a, b, c)근의 공식을 이용하여 방정식의 해를 반환(x)
  •  
  • y, a, b, c : 이차 방정식 계수 및 y
  • graphOptionGenerate(param)사용자 선택한 옵션 생성해 그래프 그리는 함수 호출
  • param : require false

 

CodePen

See the Pen dygraph Equation graph by PAPICO (@joseongryun) on CodePen.