【问题标题】:D3.js histogram bin size incrementsD3.js 直方图 bin 大小增量
【发布时间】:2025-12-25 16:10:11
【问题描述】:

我正在尝试创建救护车响应时间(以秒为单位)的直方图。 D3.js 的示例代码运行良好。我能够轻松地拼凑出漂亮的直方图。它甚至可以将响应时间以秒为单位转换为 mm:ss 格式。 我正在努力完成并需要您帮助的是这个; 如何使 bin 为 60 秒(1 分钟) 如果运行以下代码,您将看到 bin 以 50 秒为增量。这对大多数人来说是不直观的。您将如何指定垃圾箱的确切数量?对于响应时间,我希望垃圾箱为 1 分钟(60 秒),但对于在医院卸载患者,我希望垃圾箱每隔 5 分钟(300 秒)。无论如何,我想请求您的帮助以使垃圾箱成为精确值。 下面显示的是我的数据代码:

<!DOCTYPE html>

body {
    font: 10px sans-serif;
}

.bar rect {
    fill: thistle;
    shape-rendering: crispEdges;
}

.bar text {
    fill: black;
}

.axis path, .axis line {
    fill: none;
    stroke: cornsilk;
    shape-rendering: crispEdges;
}

    var values = [212,
        279,
        264,
        411,
        189,
        343,
        207,
        424,
        550,
        302,
        317,
        315,
        29,
        227,
        367,
        163,
        581,
        96,
        375,
        313,
        548,
        570,
        329,
        269,
        953,
        238,
        195,
        183,
        384,
        353,
        258,
        465,
        208,
        273,
        155,
        344,
        355,
        354,
        88,
        364,
        143,
        407,
        207,
        437,
        142,
        234,
        234,
        193,
        308,
        416,
        445,
        327,
        293,
        327,
        232,
        319,
        209,
        498,
        236,
        427,
        241,
        164,
        0,
        157,
        295,
        337,
        430,
        218,
        390,
        231,
        402,
        301,
        472,
        349,
        133,
        311,
        396,
        452,
        490,
        189,
        282,
        297,
        296,
        413,
        102,
        219,
        190,
        371,
        390,
        454,
        467,
        302,
        221,
        547]
    // Formatters for counts and times (converting numbers to Dates).
    var formatCount = d3.format(",.0f"),
            formatTime = d3.time.format("%H:%M"),
            formatMinutes = function (d) {
                return formatTime(new Date(2012, 0, 1, 0, d));
            };
    //this is the positioning of the chart
    var margin = {top: 30, right: 30, bottom: 30, left: 30},
    width = 960 - margin.left - margin.right,
            height = 500 - margin.top - margin.bottom;

    var x = d3.scale.linear()
            .domain([0, 600])
            .range([0, width]);

    // These are the number of bins in the histogram.
    var data = d3.layout.histogram()
            .bins(x.ticks(10))
            (values);

    var y = d3.scale.linear()
            .domain([0, d3.max(data, function (d) {
                    return d.y;
                })])
            .range([height, 0]);

    var xAxis = d3.svg.axis()
            .scale(x)
            .orient("bottom")
            .tickFormat(formatMinutes);

    var 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 + ")");

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

    bar.append("rect")
            .attr("x", 1)
            .attr("width", x(data[0].dx) - 1)
            .attr("height", function (d) {
                return height - y(d.y);
            });
    //this block of code makes the tick values showing how many fall into the bin
    bar.append("text")
            .attr("dy", ".75em")
            .attr("y", 6)
            .attr("x", x(data[0].dx) / 2)
            .attr("text-anchor", "middle")
            .text(function (d) {
                return formatCount(d.y);
            });

    svg.append("g")
            .attr("class", "x axis")
            .attr("transform", "translate(0," + height + ")")
            .call(xAxis);
</script>

【问题讨论】:

    标签: javascript d3.js histogram


    【解决方案1】:

    我会这样做。首先,手动计算你的刻度:

    var ticks = d3.range(0, x.domain()[1] + 1, 60);
    

    这将创建一个数组:

    [0, 60, 120, 180, 240, 300, 360, 420, 480, 540, 600]
    

    然后将此反馈给d3.histogram

    var data = d3.layout.histogram()
      .bins(ticks)
      (values);
    

    最后修复你的轴刻度:

    var xAxis = d3.svg.axis()
      .scale(x)
      .orient("bottom")
      .tickValues(ticks)
      .tickFormat(formatMinutes);
    

    大家一起:

    <!DOCTYPE html>
    <html>
    
    <head>
      <style>
        body {
          font: 10px sans-serif;
        }
        
        .bar rect {
          fill: thistle;
          shape-rendering: crispEdges;
        }
        
        .bar text {
          fill: black;
        }
        
        .axis path,
        .axis line {
          fill: none;
          stroke: cornsilk;
          shape-rendering: crispEdges;
        }
      </style>
      <script data-require="d3@3.5.3" data-semver="3.5.3" src="//cdnjs.cloudflare.com/ajax/libs/d3/3.5.3/d3.js"></script>
    </head>
    
    <body>
      <script>
        var values = [212,
            279,
            264,
            411,
            189,
            343,
            207,
            424,
            550,
            302,
            317,
            315,
            29,
            227,
            367,
            163,
            581,
            96,
            375,
            313,
            548,
            570,
            329,
            269,
            953,
            238,
            195,
            183,
            384,
            353,
            258,
            465,
            208,
            273,
            155,
            344,
            355,
            354,
            88,
            364,
            143,
            407,
            207,
            437,
            142,
            234,
            234,
            193,
            308,
            416,
            445,
            327,
            293,
            327,
            232,
            319,
            209,
            498,
            236,
            427,
            241,
            164,
            0,
            157,
            295,
            337,
            430,
            218,
            390,
            231,
            402,
            301,
            472,
            349,
            133,
            311,
            396,
            452,
            490,
            189,
            282,
            297,
            296,
            413,
            102,
            219,
            190,
            371,
            390,
            454,
            467,
            302,
            221,
            547
          ]
          // Formatters for counts and times (converting numbers to Dates).
        var formatCount = d3.format(",.0f"),
          formatTime = d3.time.format("%H:%M"),
          formatMinutes = function(d) {
            return formatTime(new Date(2012, 0, 1, 0, d));
          };
        //this is the positioning of the chart
        var margin = {
            top: 30,
            right: 30,
            bottom: 30,
            left: 30
          },
          width = 960 - margin.left - margin.right,
          height = 500 - margin.top - margin.bottom;
    
        var x = d3.scale.linear()
          .domain([0, 600])
          .range([0, width]);
    
        // These are the number of bins in the histogram.
        var ticks = d3.range(0, x.domain()[1] + 1, 60);
        
        var data = d3.layout.histogram()
          .bins(ticks)
          (values);
    
        var y = d3.scale.linear()
          .domain([0, d3.max(data, function(d) {
            return d.y;
          })])
          .range([height, 0]);
    
        var xAxis = d3.svg.axis()
          .scale(x)
          .orient("bottom")
          .tickValues(ticks)
          .tickFormat(formatMinutes);
    
        var 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 + ")");
    
        var bar = svg.selectAll(".bar")
          .data(data)
          .enter().append("g")
          .attr("class", "bar")
          .attr("transform", function(d) {
            return "translate(" + x(d.x) + "," + y(d.y) + ")";
          });
    
        bar.append("rect")
          .attr("x", 1)
          .attr("width", x(data[0].dx) - 1)
          .attr("height", function(d) {
            return height - y(d.y);
          });
        //this block of code makes the tick values showing how many fall into the bin
        bar.append("text")
          .attr("dy", ".75em")
          .attr("y", 6)
          .attr("x", x(data[0].dx) / 2)
          .attr("text-anchor", "middle")
          .text(function(d) {
            return formatCount(d.y);
          });
    
        svg.append("g")
          .attr("class", "x axis")
          .attr("transform", "translate(0," + height + ")")
          .call(xAxis);
      </script>
    </body>
    
    </html>

    【讨论】:

    • 谢谢马克。这正是我想要的!你的答案很完美。
    • 现在我如何表明这篇文章已完成?曾经有一个标志表明问题已被回答;但我在这里看不到。
    • @DavidFortMyers,不客气。要使答案被接受,请单击我的答案顶部的复选标记。
    • 点击浅灰色的检查肯定不直观。再次感谢您提供的所有帮助。