如何在 JavaScript 中计算概率密度函数

Ami*_*ran 5 html javascript statistics d3.js

注意在这个问题中,我询问了如何向图表添加分布线

这是我目前的状态: 在此处输入图片说明

我不太明白如何为直方图绘制两条分布曲线。像这样:在此处输入图片说明

这是我的代码(使用 D3.js 版本 4):

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <style>
    .bar1 rect {
      fill: rgba(0,0,255,0.6);
    }

    .bar1:hover rect{
      fill: rgba(0,0,255,0.9);
    }

    .bar1 text {
      fill: #fff;
      font: 10px sans-serif;
    }

    .bar2 rect {
      fill: rgba(255,0,0,0.6);
    }

    .bar2:hover rect{
      fill: rgba(255,0,0,0.9);
    }

    .bar2 text {
      fill: #fff;
      font: 10px sans-serif;
    }

    </style>
    <script src="https://d3js.org/d3.v4.min.js"></script>

    <script>

    function draw(data) {

      var allCongruentData = data.map(function(e){ return e.Congruent;});
      var allIncongruentData = data.map(function(e){ return e.Incongruent;});

      var formatCount = d3.format(",.0f");

      var svg = d3.select("svg"),
          margin = {top: 10, right: 30, bottom: 30, left: 30},
          width = +svg.attr("width") - margin.left - margin.right,
          height = +svg.attr("height") - margin.top - margin.bottom,
          g = svg.append("g").attr("transform", "translate(" + margin.left + "," + margin.top + ")");

      var x = d3.scaleLinear()
          .rangeRound([0, width])
          .domain([8, 36]);

      var bins1 = d3.histogram()
          .domain(x.domain())
          .thresholds(x.ticks(40))
          (allCongruentData);

      // var curve = d3.line()
      //       .x(function(d) { return ???; })
      //       .y(function(d) { return y(d.Congruent); })
      //       .curve(d3.curveCatmullRom.alpha(0.5));

      var bins2 = d3.histogram()
          .domain(x.domain())
          .thresholds(x.ticks(40))
          (allIncongruentData);

      var y = d3.scaleLinear()
          .domain([0, d3.max(bins1, function(d) { return d.length; })])
          .range([height, 0]);

      var bar1 = g.selectAll(".bar1")
        .data(bins1)
        .enter().append("g")
          .attr("class", "bar1")
          .attr("transform", function(d) { return "translate(" + x(d.x0) + "," + y(d.length) + ")"; });

      bar1.append("rect")
          .attr("x", 0.5)
          .attr("width", x(bins1[0].x1) - x(bins1[0].x0) - 1)
          .attr("height", function(d) { return height - y(d.length); });


      var bar2 = g.selectAll(".bar2")
        .data(bins2)
        .enter().append("g")
          .attr("class", "bar2")
          .attr("transform", function(d) { return "translate(" + x(d.x0) + "," + y(d.length) + ")"; });

      bar2.append("rect")
          .attr("x", 0.5)
          .attr("width", x(bins2[0].x1) - x(bins2[0].x0) - 1)
          .attr("height", function(d) { return height - y(d.length); });

      bar1.append("text")
          .attr("dy", ".75em") // why?
          .attr("y", 6)
          .attr("x", (x(bins1[0].x1) - x(bins1[0].x0)) / 2)
          .attr("text-anchor", "middle")
          .text(function(d) { return formatCount(d.length); });

      bar2.append("text")
          .attr("dy", ".75em") // why?
          .attr("y", 6)
          .attr("x", (x(bins2[0].x1) - x(bins2[0].x0)) / 2)
          .attr("text-anchor", "middle")
          .text(function(d) { return formatCount(d.length); });

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

      var legend = svg.append("g")
              .attr("class", "legend")
              .attr("transform", "translate(" + (width - 245) + "," + 40 + ")")
              .selectAll("g")
              .data(["Congruent", "Incongruent"])
              .enter().append("g");

          legend.append("text")
              .attr("y", function(d, i) {
                  return i * 30 + 5;
              })
              .attr("x", 200)
              .text(function(d) {
                  return d;
              });

          legend.append("rect")
              .attr("y", function(d, i) {
                  return i * 30 - 8;
              })
              .attr("x", 167)
              .attr("width", 20)
              .attr("height", 20)
              .attr("fill", function(d) {
                  if (d == "Congruent") {
                      return 'rgba(0,0,255,0.6';
                  } else {
                      return 'rgba(255,0,0,0.6';
                  }
              });

      // g.append("path")
      //     .datum(data)
      //     .attr("d", line);

    }
    </script>
  </head>
  <body>
    <h1>Stroop Test</h1>
    <svg width="960" height="500"></svg>
    <script type="text/javascript">
      d3.csv("stroopdata.csv", function(d) {
          d.Congruent = +d.Congruent;
          d.Incongruent = +d.Incongruent;
          return d;
        }, draw);
    </script>
  </body>
</html>
Run Code Online (Sandbox Code Playgroud)

数据如下所示:

Congruent,Incongruent
12.079,19.278
16.791,18.741
9.564,21.214
8.630,15.687
14.669,22.803
12.238,20.878
14.692,24.572
8.987,17.394
9.401,20.762
14.480,26.282
22.328,24.524
15.298,18.644
15.073,17.510
16.929,20.330
18.200,35.255
12.130,22.158
18.495,25.139
10.639,20.429
11.344,17.425
12.369,34.288
12.944,23.894
14.233,17.960
19.710,22.058
16.004,21.157
Run Code Online (Sandbox Code Playgroud)

任何帮助表示赞赏。