【发布时间】:2015-09-01 23:29:19
【问题描述】:
我想通过分箱来计算双精度数组中数字的出现频率(下面的示例数组)。与 Python numpy's histogram() 提供的功能基本相同。我处于受限环境中,可以访问基本的 Java Math 和 jblas 库,但没有其他任何东西,也没有其他第三方库,如 colt 可安装。
double[] x1 = {1, 1, 2, 2, 1, 3, 2}
我有一个单独的排序数组,它标记binEdges 的开始和结束,如下所示:
binEdges = [4.9E-324, 1.0, 1.0, 1.0, 2.0, 2.0, 2.0, 2.0, 2.0, 3.0, 4.0, 4.0, 5.0, 5.0, 7.0, 1.7976931348623157E308]
请注意,binEdges 数组可能有重复的元素,我想保留它们。因此,使用给定的binEdges 数组,频率计数的结果将如下所示:
binCounts = [0.0, 0.0, 0.0, 3.0, 0.0, 0.0, 0.0, 0.0, 3.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0]
binCounts数组结合binEdges,从左到右读取如下,注意bin区间上的大括号:
Bin interval frequency
[4.9E-324, 1.0) 0
[1.0, 1.0) 0
[1.0, 1.0) 0
[1.0, 2.0) 3 (since we have 3 ones in x1)
. .
. .
. .
我目前有以下实现,它在O(nlgn) 中运行,假设排序采用O(nlgn)。我想知道这是否可以减少到低于O(nlgn) 的值。我也在 jblas 中环顾四周,不知道用于分箱的库函数,如果这里的人们对其他本机 Java 技巧或聪明的索引方案有任何其他见解,他们可以指出我。也欢迎其他有关改进代码以减少运行时间的建议。
缩短时间很重要,因为手头的数据非常庞大。
public static double [] binCounts(double[] x, double[] binEdges){
double [] ret = new double[binEdges.length - 1];
Arrays.sort(x); // takes O(nlgn), the loop below is effectively O(n)
int k = 0;
for (int i = 0; i < binEdges.length - 1; i++) {
if (binEdges[i] == binEdges[i+1])
continue;
for (int j = k; j < x.length; j++){
if (x[j] >= binEdges[i+1])
break;
else if (x[j] >= binEdges[i] && x[j] < binEdges[i+1]){
ret[i] += 1;
k++;
}
}
}
return ret;
}
【问题讨论】: