【问题标题】:Plot regression line on a scatter plot from regression coefficients根据回归系数在散点图上绘制回归线
【发布时间】:2019-10-22 00:22:38
【问题描述】:

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

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 ))           

【问题讨论】:

    标签: javascript d3.js regression


    【解决方案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>

    【讨论】:

    • 谢谢你,马克。我不知道线发生器是什么。我会查查的。如果回归返回的点与多项式回归不同,它返回截距和斜率的线性回归不同,这会起作用吗?
    • @learner,是的,它的工作方式相同,请参阅我刚刚添加的第二个代码 sn-p。
    • @learner,顺便说一句,这是因为库返回一个混合数组/对象。可绘制的数据点是数组,而拟合的元数据(r 值等)是对象的属性。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-05-09
    • 2014-09-16
    • 1970-01-01
    • 2021-01-28
    • 2017-12-15
    • 2021-07-18
    • 2021-02-24
    相关资源
    最近更新 更多