首页 > 解决方案 > 为什么使用 spark 的 QuantileDiscretizer 得到的结果分组不均匀?

问题描述

我有一个数据集。

特征列使用org.apache.spark.ml.feature.QuantileDiscretizerspark 2.3.1的类进行分组,得到的模型分组结果不统一。

最后一个数据包反映的数据几乎是其他数据包的两倍,我在参数中设置了11个数据包,但实际只得到了10个数据包。

看看下面的程序。

import org.apache.spark.ml.feature.QuantileDiscretizer
import org.apache.spark.ml.feature.Bucketizer
val model = new QuantileDiscretizer()
    .setInputCol("features")
    .setOutputCol("level")
    .setNumBuckets(11)
    .setHandleInvalid("keep")
    .fit(df)
println(model.getSplits.mkString(", "))
model
    .transform(df)
    .groupBy("level")
    .count
    .orderBy("level")
    .show

输出:

-Infinity, 115.0, 280.25, 479.75, 712.5, 1000.0, 1383.37, 1892.75, 2690.93, 4305.0, Infinity
+-----+------+                                                                  
|level| count|
+-----+------+
| null|  9113|
|  0.0| 55477|
|  1.0| 52725|
|  2.0| 54657|
|  3.0| 53592|
|  4.0| 54165|
|  5.0| 54732|
|  6.0| 52915|
|  7.0| 54090|
|  8.0| 53393|
|  9.0|107369|
+-----+------+

分别对最后一组数据进行分组:

val df1 = df.where("features >= 4305.0")
val model1 = new QuantileDiscretizer()
    .setInputCol("features")
    .setOutputCol("level")
    .setNumBuckets(2)
    .setHandleInvalid("keep")
    .fit(df1)

println(model1.getSplits.mkString(", "))
model1
    .transform(df1)
    .groupBy("level")
    .count
    .orderBy("level")
    .show

输出:

-Infinity, 20546.12, Infinity
+-----+-----+                                                                   
|level|count|
+-----+-----+
|  0.0|53832|
|  1.0|53537|
+-----+-----+

如果我手动指定要分组的石斑鱼边界:

val splits = Array(Double.NegativeInfinity, 
    115.0, 280.25, 479.75, 712.5, 1000.0, 1383.37, 1892.75, 2690.93, 4305.0, 
    20546.12, Double.PositiveInfinity)
val model = new Bucketizer()
    .setInputCol("features")
    .setOutputCol("level")
    .setHandleInvalid("keep")
    .setSplits(splits)
model
.transform(df)
.groupBy("level")
.count
.orderBy("level")
.show

输出:

+-----+-----+                                                                   
|level|count|
+-----+-----+
| null| 9113|
|  0.0|55477|
|  1.0|52725|
|  2.0|54657|
|  3.0|53592|
|  4.0|54165|
|  5.0|54732|
|  6.0|52915|
|  7.0|54090|
|  8.0|53393|
|  9.0|53832|
| 10.0|53537|
+-----+-----+

请告诉我为什么QuantileDiscretizer会有这样的行为?

如果我想对原始数据进行均匀分组怎么办?

标签: apache-sparksplitapache-spark-mlquantilediscretization

解决方案


推荐阅读