我有一系列像这样的花车:
[1.91, 2.87, 3.61, 10.91, 11.91, 12.82, 100.73, 100.71, 101.89, 200]
现在,我想像这样对数组进行分区:
[[1.91, 2.87, 3.61] , [10.91, 11.91, 12.82] , [100.73, 100.71, 101.89] , [200]]
由于群集支持较少,// [200]将被视为异常值
我必须为几个数组找到这种段,我不知道分区大小应该是多少。我尝试使用hierarchical clustering (Agglomerative)来做到这一点,它给了我满意的结果。然而,问题是,我被建议不要将聚类算法用于一维问题,因为它们不是理论上的理由(因为它们是多维数据)。
我花了很多时间来寻找解决方案。但是,建议似乎完全不同,如:this和this VS. this和this以及this。
我找到了另一个建议而不是群集,即natural breaks optimization。但是,这也需要声明分区号,如K-means(右?)。
这很混乱(特别是因为我必须在几个阵列上执行这种分段,并且不可能知道最佳分区号。)
是否有任何方法可以找到分区(因此我们可以通过一些理论上的合理性来减少分区内的差异并最大化分区之间的差异)?
任何指向文章/论文的指针(如果有可用的C / C ++ / Java实现)都有一些理论上的理由对我很有用。
答案 0 :(得分:10)
我想我会对数据进行排序(如果尚未对数据进行排序),则采用相邻的差异。将差异除以数字中较小的数字,以获得百分比变化之间的差异。设置阈值,当更改超过该阈值时,启动一个新的"集群"。
编辑:C ++中的快速演示代码:
#include <iostream>
#include <vector>
#include <algorithm>
#include <iterator>
#include <numeric>
#include <functional>
int main() {
std::vector<double> data{
1.91, 2.87, 3.61, 10.91, 11.91, 12.82, 100.73, 100.71, 101.89, 200
};
// sort the input data
std::sort(data.begin(), data.end());
// find the difference between each number and its predecessor
std::vector<double> diffs;
std::adjacent_difference(data.begin(), data.end(), std::back_inserter(diffs));
// convert differences to percentage changes
std::transform(diffs.begin(), diffs.end(), data.begin(), diffs.begin(),
std::divides<double>());
// print out the results
for (int i = 0; i < data.size(); i++) {
// if a difference exceeds 40%, start a new group:
if (diffs[i] > 0.4)
std::cout << "\n";
// print out an item:
std::cout << data[i] << "\t";
}
return 0;
}
结果:
1.91 2.87 3.61
10.91 11.91 12.82
100.71 100.73 101.89
200
答案 1 :(得分:3)
群集通常采用多维数据。
如果您有一维数据,排序,然后使用核心密度估算,或者只扫描最大间隙。
在一维中,问题变得非常容易,因为数据可以进行排序。如果你使用聚类算法,很遗憾不利用它,所以请改用1维方法!
考虑找到1维数据中的最大差距。它是微不足道的:sort(n log n,但在实践中尽可能快),然后查看两个相邻的值,以获得最大的差异。
现在尝试在2维中定义“最大间隙”,并找到一种有效的算法来定位它......