【问题标题】:Javascript D3 Histogram: thresholds producing wrong number of binsJavascript D3直方图:阈值产生错误数量的垃圾箱
【发布时间】:2017-09-08 21:20:57
【问题描述】:

我正在使用 D3 创建一个直方图 JS 脚本,一切似乎都正常工作......除了 bin 的数量。

以下是我的代码的相关部分:

//Define the scales for the x and y attributes
var x = d3.scaleBand()
    .range([0, width])
    .padding(configProperties.barPadding);
var y = d3.scaleLinear()
    .range([height,0]);

//Create the bins
var bins = d3.histogram()
    .domain(d3.extent(data))
    .thresholds(configProperties.binsCount)
    (data);

console.log("number of bins: " + bins.length); //9
console.log("intended number of bins: " + configProperties.binsCount); //10

如果我将 configProperties.binsCount 设置为 9,bins.length 仍然是 9。 如果我将 configProperties.binsCount 设置为 14,bins.length 仍然是 9。

如果我将 binsCount 设置为 15 或更高,但是... bins.length 输出 23。

我对 histogram.thresholds 如何基于the documentation 工作的理解是,如果我给它一个值,它会将数据分成许多 + 1 个相等的段(即许多箱)。但是,它似乎根本没有这样做。我能找到的所有示例代码似乎都表明我正在正确使用它,但我无法获得所需的 bin 数量。

我也尝试使用d3.ticks 作为阈值参数,但我遇到了同样的问题。

我有什么遗漏吗?它与我的域有关吗?提前致谢。

【问题讨论】:

    标签: javascript d3.js histogram data-visualization


    【解决方案1】:

    我意识到这有点老了,Gerardo 解释了如何做你所要求的,但他实际上并没有回答问题的为什么。所以这就是,以防其他人遇到这个问题并且很好奇。如果您将一个数字传递给 thresholds 函数,D3 会找到接近该数字的 bin 数量,因此阈值是“不错的”数字。正是这些“好”数字的选择导致箱数与您指定的不同。

    因此,如果您的数据从 0 变为 24.37,并且您请求 8 个 bin,则阈值不会是 3.481428571428 的倍数...(= 24.37 / (8-1))。相反,D3 将选择一个“不错”的最大值 25,阈值将是 2.5 的倍数(制作 10 个垃圾箱)或 5 的倍数(制作 5 个垃圾箱)。这些数字更适合显示在图表上,如果人类手动制作直方图,他们可能会选择这些数字。

    【讨论】:

      【解决方案2】:

      您将 count(即简单数字)传递给 thresholds 函数,不是数组。

      您看到的是传递数字时的预期行为。根据same docs

      如果指定了一个计数而不是一个阈值数组,那么该域将被均匀地划分为近似计数的 bin;

      让我们在这个演示中看到它:

      var data = d3.range(100);
      
      const histogram = d3.histogram()
        .value(d => d)
        .thresholds(5);
      
      var bins = histogram(data);
      
      console.log("The number of bins is " + bins.length)
      <script src="https://d3js.org/d3.v4.js"></script>

      如您所见,count 为 5,bin 的数量也是 5。

      但是,如果您传递一个 array,则行为是您所期望的:bin 的数量将是 array.length + 1:

      阈值定义为值数组 [x0, x1, ...]。任何小于 x0 的值都将放在第一个 bin 中;任何大于或等于 x0 但小于 x1 的值都将放在第二个 bin 中;等等。因此,生成的直方图将具有 thresholds.length + 1 个 bin。

      这里是演示:

      var data = d3.range(100);
      
      const histogram = d3.histogram()
        .value(d => d)
        .thresholds([10, 30, 50, 70, 90]);
      
      var bins = histogram(data);
      
      console.log("The number of bins is " + bins.length)
      <script src="https://d3js.org/d3.v4.js"></script>

      如您所见,数组有 5 个值,分箱数为 6。

      最后,请记住,分箱的实际数量取决于您传递给直方图生成器的数据。这解释了您在问题中描述的其他结果。

      【讨论】:

      • 感谢您的回复!所以,我想为什么我没有得到预期数量的垃圾箱的真正答案是因为我的数据集不允许它?我觉得这有点令人困惑,因为例如,如果我使用在线直方图制作工具,那么使用任意数量的箱(即,根据我的示例为 10 个)绘制数据图表都没有问题。Here is a screenshot 显示我的意思.
      • 我想我通过手动计算我自己的 array 根据数据和提供的阈值以及 binsCount 找到了如何做到这一点。这似乎比使用 count 更好。再次感谢您帮助我思考这个问题。
      猜你喜欢
      • 2016-12-31
      • 1970-01-01
      • 2017-12-01
      • 2022-06-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-05-24
      • 2021-04-20
      相关资源
      最近更新 更多