根据回归系数在散点图上绘制回归线

时间:2019-06-06 13:10:19

标签: javascript d3.js regression

我正在尝试使用以下方法绘制回归线:

https://observablehq.com/@harrystevens/introducing-d3-regression#linear

我遵循了本教程并添加了以下代码,

dataLinear = [{x: 8, y: 3},{x: 2, y: 10},{x: 11, y: 3},{x: 6, y: 6},{x: 5, y: 8},{x: 4, y: 12},{x: 12, y: 1},{x: 9, y: 4},{x: 6, y: 9},{x: 1, y: 14}]

linearRegression = d3.regressionLinear()
   .x(d => d.x)
   .y(d => d.y)
   .domain([-1.7, 16]);
res = linearRegression(dataLinear)
console.log(res)

现在,我得到的系数为:


0: Array [ -1.7, 15.961993243243242 ]
​
1: Array [ 16, -3.621621621621621 ]
​
a: -1.1064189189189189
​
b: 14.08108108108108
​
length: 2
​
predict: function S()
​
rSquared: 0.8731378215564962

如何使用系数在散点图的顶部绘制线?

编辑:

在了解什么是行生成器之前,我使用了以下代码:

         var a_reg_line = svg.append("svg:line")
        .attr("x1", xScale(0))
        .attr("y1", yScale(res.b))
        .attr("x2", xScale(10))
        .attr("y2", yScale( (10*res.a) + res.b ))           

1 个答案:

答案 0 :(得分:1)

看起来库是已构建的,因此您可以将其返回res传递给d3.line生成器:

...
let line = d3.line()
  .x((d) => x(d[0]))
  .y((d) => y(d[1]));

svg.append("path")
  .datum(res)
  .attr("d", line)
...

这是使用d3进行绘制的完整简化示例:

<!DOCTYPE html>
<html>

<head>
  <script src="https://d3js.org/d3.v5.min.js"></script>
  <script src="https://cdn.jsdelivr.net/gh/HarryStevens/d3-regression@master/dist/d3-regression.min.js"></script>

</head>

<body>
  <script>
    let dataLinear = [{
      x: 8,
      y: 3
    }, {
      x: 2,
      y: 10
    }, {
      x: 11,
      y: 3
    }, {
      x: 6,
      y: 6
    }, {
      x: 5,
      y: 8
    }, {
      x: 4,
      y: 12
    }, {
      x: 12,
      y: 1
    }, {
      x: 9,
      y: 4
    }, {
      x: 6,
      y: 9
    }, {
      x: 1,
      y: 14
    }]

    let linearRegression = d3.regressionLinear()
      .x(d => d.x)
      .y(d => d.y)
      .domain([-1.7, 16]);
    let res = linearRegression(dataLinear)

    let margin = {
        top: 30,
        right: 20,
        bottom: 30,
        left: 50
      },
      width = 600 - margin.left - margin.right,
      height = 270 - margin.top - margin.bottom;

    let x = d3.scaleLinear().range([0, width]);
    let y = d3.scaleLinear().range([height, 0]);

    let svg = d3.select("body")
      .append("svg")
      .attr("width", width + margin.left + margin.right)
      .attr("height", height + margin.top + margin.bottom)
      .append("g")
      .attr("transform",
        "translate(" + margin.left + "," + margin.top + ")");

    x.domain(d3.extent(dataLinear, (d) => d.x));
    y.domain(d3.extent(dataLinear, (d) => d.y));

    // Add the valueline path.
    svg.selectAll("circle")
      .data(dataLinear)
      .enter()
      .append("circle")
      .attr("r", 5)
      .style("fill", "steelblue")
      .attr("cx", (d) => x(d.x))
      .attr("cy", (d) => y(d.y));

    let line = d3.line()
      .x((d) => x(d[0]))
      .y((d) => y(d[1]));

    svg.append("path")
      .datum(res)
      .attr("d", line)
      .style("stroke", "steelblue")
      .style("stroke-width", "2px");

    svg.append("g")
      .attr("transform", "translate(0," + height + ")")
      .call(d3.axisBottom(x));

    svg.append("g")
      .call(d3.axisLeft(y));
  </script>
</body>

</html>

四元回归:

<!DOCTYPE html>
<html>

<head>
  <script src="https://d3js.org/d3.v5.min.js"></script>
  <script src="https://cdn.jsdelivr.net/gh/HarryStevens/d3-regression@master/dist/d3-regression.min.js"></script>

</head>

<body>
  <script>
    let dataLinear = [{
      x: 8,
      y: 3
    }, {
      x: 2,
      y: 10
    }, {
      x: 11,
      y: 3
    }, {
      x: 6,
      y: 2
    }, {
      x: 5,
      y: 2
    }, {
      x: 4,
      y: 12
    }, {
      x: 12,
      y: 1
    }, {
      x: 9,
      y: 4
    }, {
      x: 6,
      y: 9
    }, {
      x: 1,
      y: 14
    }]

    let quadRegression = d3.regressionQuad()
      .x(d => d.x)
      .y(d => d.y)
      .domain([-1.7, 16]);
    let res = quadRegression(dataLinear)

    let margin = {
        top: 30,
        right: 20,
        bottom: 30,
        left: 50
      },
      width = 600 - margin.left - margin.right,
      height = 270 - margin.top - margin.bottom;

    let x = d3.scaleLinear().range([0, width]);
    let y = d3.scaleLinear().range([height, 0]);

    let svg = d3.select("body")
      .append("svg")
      .attr("width", width + margin.left + margin.right)
      .attr("height", height + margin.top + margin.bottom)
      .append("g")
      .attr("transform",
        "translate(" + margin.left + "," + margin.top + ")");

    x.domain(d3.extent(dataLinear, (d) => d.x));
    y.domain(d3.extent(dataLinear, (d) => d.y));

    // Add the valueline path.
    svg.selectAll("circle")
      .data(dataLinear)
      .enter()
      .append("circle")
      .attr("r", 5)
      .style("fill", "steelblue")
      .attr("cx", (d) => x(d.x))
      .attr("cy", (d) => y(d.y));

    let line = d3.line()
      .x((d) => x(d[0]))
      .y((d) => y(d[1]));

    svg.append("path")
      .datum(res)
      .attr("d", line)
      .style("fill", "none")
      .style("stroke", "steelblue")
      .style("stroke-width", "2px");

    svg.append("g")
      .attr("transform", "translate(0," + height + ")")
      .call(d3.axisBottom(x));

    svg.append("g")
      .call(d3.axisLeft(y));
  </script>
</body>

</html>