【问题标题】:Java - generate compartments / intervals from min, max and countJava - 从最小值、最大值和计数生成隔间/间隔
【发布时间】:2015-07-10 09:16:11
【问题描述】:

我需要通过给出一组值来为地图上的图例生成值。 是否有任何 Java 库中的函数可以从值数组和计数值生成范围或隔间?比如:

Integer[] getIntervals(Number[] values , int count);

示例用法:

getIntervals([10, 33.5, 45.98, 62, 77,80 ], 5) 将返回 [10, 24, 38, 52, 64, 80]

这很容易由我自己编写,但它必须聪明地在图例上显示它。聪明的意思是生成对图例有意义的数字。我不知道如何用英语描述它,所以我附上一个屏幕截图,说明我的意思。

如果上述功能按照我想要的方式智能,它将返回: [10, 30, 50, 70, 90] 或类似的东西。

这仍然是我可以自己写的东西,但也许这已经在某个地方完成了?我查看了 Apache Commons MathUtils 和 Apache Commons Math,但找不到我需要的东西。

编辑:我发现 Apache Commons 中有一个 Percentile 类,这似乎是我需要使用的,但我的数学太弱了。

【问题讨论】:

  • 不清楚你在问什么。为什么上面的数组不比下面的数组好?你如何定义一个聪明的方法来做到这一点?据我了解,您需要一个生成数字列表的函数,每对邻居(从左到右)都比前一对有更大的差异。
  • 您希望getIntervals 计算要在图例中使用的范围吗?您希望范围大小相等还是希望每个范围中的值数量尽可能均匀?
  • 是否存在符合您主观(且未公开)“聪明”标准的东西?可能,但可能不会。

标签: java math numbers range intervals


【解决方案1】:

您的问题需要解决,但我选择将其解读为“我正在尝试为一系列输入值构建间隔良好的刻度以用于可视化目的”。在这种情况下,我建议您仔细查看how D3.js implements such scales。是的,Javascript 不是 Java——但是 D3.js 是一个著名的可视化库,你描述的问题是一个众所周知的可视化问题,并且语法与 Java 非常相似,可以让你很容易地适应这些想法.

简而言之,粗略地翻译:

public interface LinearScale {
    /**
     * build a scale from min to max; see d3 linear.domain()
     * and then expand it to make it end in nice, round numbers; 
     *  see d3 linear.nice()
     */
    void setNiceDomain(double min, double max);
    /**
     * set number of threshold values; see d3 linear.ticks()
     *   and return their values
     */
    double[] setThresholdCount(int ticks);
    /**
     * gets the largest threshold that is <= a given value
     */
    double map(double value);
}

(JS) 源代码可在https://github.com/mbostock/d3/blob/master/src/scale/linear.js 获得;选择sn-ps(来自linear.ticks()的实现):

function d3_scale_linearTickRange(domain, m) {
    if (m == null) m = 10;

    var extent = d3_scaleExtent(domain),
        span = extent[1] - extent[0],
        step = Math.pow(10, Math.floor(Math.log(span / m) / Math.LN10)),
        err = m / span * step;

    // Filter ticks to get closer to the desired count.
    if (err <= .15) step *= 10;
    else if (err <= .35) step *= 5;
    else if (err <= .75) step *= 2;

    // Round start and stop values to step interval.
    extent[0] = Math.ceil(extent[0] / step) * step;
    extent[1] = Math.floor(extent[1] / step) * step + step * .5; // inclusive
    extent[2] = step;
    return extent;
}

function d3_scale_linearTicks(domain, m) {
    return d3.range.apply(d3, d3_scale_linearTickRange(domain, m));
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-02-19
    • 1970-01-01
    • 1970-01-01
    • 2022-11-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-12-02
    相关资源
    最近更新 更多