是否可以使用dygraphs显示插值数据?

时间:2017-03-17 12:48:20

标签: javascript charts interpolation dygraphs

我最近几个月一直在用dygraph工作。这是一个令人难以置信的库,我有很好的结果,但我有一些问题,找到插入不同信号数据的方式,以显示在同一图表。

我从不同传感器收到的数据对于不同的样本具有不同的时间戳,因此对于x ax时间戳的大多数点,我只有一个信号的值。图表完美地绘制,但我希望看到我指向的x点中其余信号的插值。下面我有我得到的图表。

enter image description here

阅读dygraph documentation我已经看到,当你有独立系列时,在x轴的那一点没有数据的信号至少可以看到“undefined”值。

我用来绘制数据的csv如下所示。它具有与dygraph文档中指示的相同结构,但我也没有得到这个未定义的标签。

TIME,LH_Fuel_Qty,L_Left_Sensor_NP 1488801288048,,1.4411650490795007 1488801288064,0.478965502446834, 1488801288133,,0.6372882768113235 1488801288139,1.131315227899919, 1488801288190,1.847605177130475, 1488801288207,,0.49655791428536067 1488801288258,0.45488168748987334, 1488801288288,,1.3756073145270766 1488801288322,0.5636921255908185, 1488801288358,,1.1193344122758362

提前致谢。

3 个答案:

答案 0 :(得分:1)

似乎最好的方法是在将数据提交给dygraph调用之前按下数据。这意味着以下步骤: 1)将csv文件解析为数组数组。 2)遍历阵列的每一行以找到孔的位置 3)插补以填补这些孔 4)修改由dygraph显示的构造数组 5)调用dygraph

不是最有吸引力的代码,但似乎有用......

function findNextValueIndex(data, column, start) {
    var rows = data.length;

    for(var i=start;i<rows;i++) {
        if(data[i][column].length>0) return(i);
    }
    return(-1);
}

function interpolate(t0, t1, tmid, v0, v1) {
    return((v0 + (tmid-t0)/(t1-t0) * (v1-v0)).toString());
}

function parseCSV(string) {

    var data = [];

    // first get the number of lines:

    var lines = string.split('\n');

    // now split the first line to retrieve the headings

    var headings = lines[0].split(",");
    var cols = headings.length;

    // now get the data

    var rows=0;
    for(var i=1;i<lines.length;i++) {
        if(lines[i].length>0) {
            data[rows] = lines[i].split(",");
            rows++;
        }
    }

    // now, fill in the blanks - start by finding the first value for each column of data

    var vals = [];
    var times = [];

    for(var j=1;j<cols;j++) {
        var index = findNextValueIndex(data,j,0);
        vals[j] = parseFloat(data[index][j]);
    }

    // now put those start values at the beginning of the array 
    // there is no way to calculate the previous value of the sensor missing from the first sample 
    // so we use the first reading and duplicate it
    for(var j=1;j<cols;j++) {
        data[0][j] = vals[j].toString();
        times[j] = parseInt(data[0][0]);
    }

    // now step through the rows and interpolate the missing values
    for(var i=1;i<rows;i++) {
        for(var j=1;j<cols;j++) {
            if(data[i][j].length>0) {
                vals[j] = parseFloat(data[i][j]);
                times[j] = parseInt(data[i][0]);
            }
            else {
                var index = findNextValueIndex(data,j,i);
                if(index<0) // no more data in this column
                    data[i][j] = vals[j].toString();
                else
                    data[i][j] = interpolate(times[j],parseInt(data[index][0]),parseInt(data[i][0]),vals[j],data[index][j]);
            }
        }        
    }
    // now convert from strings to integers and floats so dygraph can handle it
    // I've also changed the time value so that it is relative to the first element
    // it will be shown in milliseconds
    var time0 = parseInt(data[0][0]);
    for(var i=0;i<rows;i++) {
        data[i][0] = parseInt(data[i][0]) - time0;
        for(var j=1;j<cols;j++) {
            data[i][j] = parseFloat(data[i][j]);           
        } 
    }
    var obj = {
        labels: headings,
        data: data
    }

    return(obj);
}

window.onload = function () {

    var data_obj = parseCSV(document.getElementById('csvdata').innerHTML);


      new Dygraph(
        document.getElementById('graph'), data_obj.data,
        {
          labels: data_obj.labels,
          connectSeparatedPoints: true,
          drawPoints: true
        }
      );
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/dygraph/2.0.0/dygraph.js"></script>
<div id="graph" style="height:200px;"></div>

<pre id="csvdata" style="display:none">
TIME,LH_Fuel_Qty,L_Left_Sensor_NP
1488801288048,,1.4411650490795007
1488801288064,0.478965502446834,
1488801288133,,0.6372882768113235
1488801288139,1.131315227899919,
1488801288190,1.847605177130475,
1488801288207,,0.49655791428536067
1488801288258,0.45488168748987334,
1488801288288,,1.3756073145270766
1488801288322,0.5636921255908185,
1488801288358,,1.1193344122758362
</pre>

答案 1 :(得分:1)

这种方法不会向csv数据添加任何数据,并且在移动鼠标时仍会为所有列提供插值。它为dygraph中的mousemove事件添加了一个监听器,并为所有数据插入最近的点。目前我只是在图表之后的额外DIV中显示它,但是你可以随意显示它:

function findNextValueIndex(data, column, start) {
  var rows = data.length;

  for (var i = start; i < rows; i++) {
    if (data[i][column] != null) return (i);
  }
  return (-1);
}

function findPrevValueIndex(data, column, start) {

  for (var i = start; i >= 0; i--) {
    if (data[i][column] != null) return (i);
  }
  return (-1);
}

function interpolate(t0, t1, tmid, v0, v1) {
  return (v0 + (tmid - t0) / (t1 - t0) * (v1 - v0));
}

function showValues(headers, colors, vals) {
  var el = document.getElementById("info");
  var str = "";
  for (j = 1; j < headers.length; j++) {
    str += '<p style="color:' + colors[j] + '";>' + headers[j] + ": " + vals[j] + "</p>";
  }
  el.innerHTML = str;
  document.getElementById("hiddenDiv").style.display = "none";
}

function movecustom(event, dygraph, point) {
  var time = dygraph.lastx_;
  var row = dygraph.lastRow_;
  var vals = [];
  var headers = [];
  var colors = [];
  var cols = dygraph.rawData_[0].length;
  
  // draw a line on the chart showing the selected location
  var canvas = dygraph.canvas_;
  var ctx = canvas.getContext("2d");

  ctx.beginPath();
  ctx.lineWidth = 1;
  ctx.strokeStyle = "rgba(0,200,200,0.1)";
  ctx.moveTo( dygraph.selPoints_[0].canvasx, 0);
  ctx.lineTo( dygraph.selPoints_[0].canvasx, 1000);
  ctx.stroke();
  
  
  for (var j = 1; j < cols; j++) {
    colors[j] = dygraph.colors_[j - 1];
    if (dygraph.rawData_[row][j] == null) {
      var prev = findPrevValueIndex(dygraph.rawData_, j, row - 1);
      var next = findNextValueIndex(dygraph.rawData_, j, row + 1);
      if (prev < 0)
        vals[j] = dygraph.rawData_[next][j];
      else if (next < 0)
        vals[j] = dygraph.rawData_[prev][j];
      else {
        vals[j] = interpolate(dygraph.rawData_[prev][0], dygraph.rawData_[next][0], time, dygraph.rawData_[prev][j], dygraph.rawData_[next][j]);
      }
    } else {
      vals[j] = dygraph.rawData_[row][j];
    }
  }

  headers = Object.keys(dygraph.setIndexByName_);

  showValues(headers, colors, vals);
}

window.onload = function() {

  new Dygraph(
    document.getElementById('graph'), document.getElementById('csvdata').innerHTML, {
      connectSeparatedPoints: true,
      drawPoints: true,
      labelsDiv: "hiddenDiv",
      interactionModel: {
        'mousemove': movecustom
      }
    }
  );
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/dygraph/2.0.0/dygraph.js"></script>

<div id="graph" style="height:120px;"></div>

<div id="info"></div>
<div id="hiddenDiv" style="display:none"></div>

<pre id="csvdata" style="display:none">
TIME,LH_Fuel_Qty,L_Left_Sensor_NP
1488801288048,,1.4411650490795007
1488801288064,0.478965502446834,
1488801288133,,0.6372882768113235
1488801288139,1.131315227899919,
1488801288190,1.847605177130475,
1488801288207,,0.49655791428536067
1488801288258,0.45488168748987334,
1488801288288,,1.3756073145270766
1488801288322,0.5636921255908185,
1488801288358,,1.1193344122758362
</pre>

答案 2 :(得分:0)

connectSeparatedPoints: true

不能满足您的需求?