java - 如何在java中使用apache math 3.0为直方图生成bin?

Posted

技术标签:

【中文标题】java - 如何在java中使用apache math 3.0为直方图生成bin?【英文标题】:how to generate bins for histogram using apache math 3.0 in java? 【发布时间】:2012-06-02 22:16:19 【问题描述】:

我一直在寻找使用 apache common math 3.0 为特定数据集生成 bin(通过指定低频段、高频段和所需的 bin 数量)。我看过频率http://commons.apache.org/math/apidocs/org/apache/commons/math3/stat/Frequency.html 但它并没有给我我想要的东西。我想要一种方法,可以给我一个区间内的值的频率(例如:有多少值在 0 到 5 之间)。有什么建议或想法吗?

【问题讨论】:

你受限于 Apache 吗?这听起来与 Guava's SortedMultiset 的用例一模一样。 @Louis Wasserman 是的,我仅限于 Apache math 3.0,因为它提供了其他拟合和插值功能。 如果您使用的是 Java 的更新版本,您可以使用 Java Streams API 来执行此操作。请参阅下面的answer。 【参考方案1】:

这是相同功能的基于 Java 流的实现。

使用一些有用的范围、过滤和计数功能。

public static Long[] calcHistogram(Double[] data, Double min, Double max, Integer numBins) 
  final var interval = (max - min) / numBins;

  return IntStream.range(0, numBins)
      .boxed()
      .map(n -> 
        var binStart = min + n * interval;
        var binEnd = min + (n + 1) * interval;
        return Arrays.stream(data).filter(d -> d >= binStart && d < binEnd).count();
      )
      .toArray(Long[]::new);

【讨论】:

【参考方案2】:

这是@Altair7852 的回答。

如果你想为你的y值生成x值bin interval(每个bin中的频率..akahistogram[] at index i)这里是完整的方法

    private fun displayHistogram(binCount: Int, data: DoubleArray) 
        val histogram = DoubleArray(binCount)
        val distribution = org.apache.commons.math3.random.EmpiricalDistribution(binCount)
        distribution.load(data)

        var k = 0
        for (stats in distribution.binStats) 
            histogram[k++] = stats.n.toDouble()
        

        val binSize = (data.max()!!.toDouble() - data.min()!!.toDouble()) / binCount

        for (i in 0 until histogram.size) 
            series2?.appendData(DataPoint(generateHistogramXValues(data.min()!!.toDouble(), histogram.size, binSize)[i], histogram[i]), false, histogram.count())
        
    

这里是x值的生成方法

        val xValuesArray = DoubleArray(numberOfBIns)
        for (i in 0 until numberOfBIns) 
            if (i == 0)
                xValuesArray[i] = min
            else
                val previous = xValuesArray[i-1]
                xValuesArray[i] = previous+binSize
            
        
        return xValuesArray
    

我正在使用GraphView 图形库在android 上执行此操作,但您可以在任何库上使用它。

【讨论】:

【参考方案3】:

据我所知,Apache Commons 中没有好的直方图类。我最终写了自己的。如果你想要的只是从 min 到 max 线性分布的 bin,那么它很容易编写。

可能是这样的:

public static int[] calcHistogram(double[] data, double min, double max, int numBins) 
  final int[] result = new int[numBins];
  final double binSize = (max - min)/numBins;

  for (double d : data) 
    int bin = (int) ((d - min) / binSize);
    if (bin < 0)  /* this data is smaller than min */ 
    else if (bin >= numBins)  /* this data point is bigger than max */ 
    else 
      result[bin] += 1;
    
  
  return result;

编辑:这是一个示例。

double[] data =  2, 4, 6, 7, 8, 9 ;
int[] histogram = calcHistogram(data, 0, 10, 4);
// This is a histogram with 4 bins, 0-2.5, 2.5-5, 5-7.5, 7.5-10.
assert histogram[0] == 1; // one point (2) in range 0-2.5
assert histogram[1] == 1; // one point (4) in range 2.5-5.
// etc..

【讨论】:

但是如何获得每个 bin 的频率?我没有在 Apache Math 3.0 中找到任何类或方法。 每个 bin 的频率? result[i] 为您提供i-th bin 中有多少数据点。如果您想要频率(比例),只需执行result[i] / data.length... Max,我认为你的代码有一个小错误......请参阅下面发布的我的更正。谢谢。 如何获得 bin 数组,您能帮忙吗? 频率数组 *【参考方案4】:

我认为您的代码有错误 -- 请参阅下面的更正代码:

public static int[] calcHistogram(double[] data, double min, double max, int numBins) 
  final int[] result = new int[numBins];
  final double binSize = (max - min)/numBins;

  for (double d : data) 
    int bin = (int) ((d - min) / binSize); // changed this from numBins
    if (bin < 0)  /* this data is smaller than min */ 
    else if (bin >= numBins)  /* this data point is bigger than max */ 
    else 
      result[bin] += 1;
    
  
  return result;

【讨论】:

这应该是对 Max 答案的编辑,而不是单独的答案【参考方案5】:

这是使用 Apache Commons Math 3 实现直方图的简单方法:

final int BIN_COUNT = 20;
double[] data = 1.2, 0.2, 0.333, 1.4, 1.5, 1.2, 1.3, 10.4, 1, 2.0; 

long[] histogram = new long[BIN_COUNT];
org.apache.commons.math3.random.EmpiricalDistribution distribution = new org.apache.commons.math3.random.EmpiricalDistribution(BIN_COUNT);
distribution.load(data);
int k = 0;
for(org.apache.commons.math3.stat.descriptive.SummaryStatistics stats: distribution.getBinStats())

    histogram[k++] = stats.getN();

【讨论】:

也可以从 EmpiricalDistribution#getUpperBounds 获取区间边界。 Commons Math 是否提供了一个函数,可以根据您要分箱的人口规模建议“好”数量的分箱? 来自文档 使用说明:binCount 默认设置为 1000。一个好的经验法则是将 bin 计数设置为大约输入文件的长度除以 10。输入文件必须是一个纯文本文件,每行包含一个有效的数字条目。见commons.apache.org/proper/commons-math/javadocs/api-3.6/org/…

以上是关于java - 如何在java中使用apache math 3.0为直方图生成bin?的主要内容,如果未能解决你的问题,请参考以下文章

Cause: java.lang.ClassCastException: java.lang.String cannot be cast to org.apache.ibatis.mapping.M

如何在 java 中使用 Apache spark 计算中位数和众数?

如何在 Java 中使用 Apache ActiveMQ 实现基于条件的队列

Apache Spark:如何使用 Java 在 dataFrame 中的空值列中插入数据

在 Java 中,如何创建等效的 Apache Avro 容器文件,而不必强制使用文件作为媒介?

如何使用 Apache Commons Codec 在 Java 中解码 JWT(标题和正文)?