如何使用avg和stddev查找异常值?

时间:2017-06-22 19:54:01

标签: java apache-spark apache-spark-sql

我正在对数据集进行冲突过滤<'Row>使用org.apache.spark.sql.functions库中内置函数的MEAN()和STDEV()。

这是我正在使用的数据集(前10名):

Name    Size    Volumes
File1   1030    107529
File2   997     106006
File3   1546    112426
File4   2235    117335
File5   2061    115363
File6   1875    114015
File7   1237    110002
File8   1546    112289
File9   1030    107154
File10  1339    110276

我目前要做的是找到此数据集中的异常值。为此,我需要使用95%规则找到SIZE和VOLUMES为异常值的行:μ - 2σ≤X≤μ+2σ

这是我想在此数据集上运行的类似SQL的查询:

SELECT * FROM DATASET
WHERE size < (SELECT (AVG(size)-2STDEV(size)) FROM DATASET)
OR size > (SELECT (AVG(size)+2STDEV(size)) FROM DATASET)
OR  volumes < (SELECT (AVG(volumes)-2STDEV(volumes)) FROM DATASET)
OR volumes > (SELECT (AVG(volumes)+2STDEV(volumes)) FROM DATASET)

我不知道如何实现嵌套查询,我很难找到解决这个问题的方法。 此外,如果您碰巧知道获得我想要的其他方式,请随时分享。

这是我试图做的但我收到错误:

Column meanSize = functions.mean(size);
Column meanRecords = functions.mean(records);
Column stdSize = functions.stddev(size);
Column stdRecords = functions.stddev(records);

Column lowerSizeThreshold = size.lt((meanSize.minus(stdSize).minus(stdSize)));
Column upperSizeThreshold = size.gt(meanSize.plus(stdSize).plus(stdSize));
Column lowerRecordsThreshold = records.lt(meanRecords.minus(stdRecords).minus(stdRecords));
Column upperRecordsThreshold = records.gt(meanRecords.plus(stdRecords).plus(stdRecords));

Dataset<Row> outliers = dataFrame.where(lowerSizeThreshold.or(upperSizeThreshold).or(lowerRecordsThreshold).or(upperRecordsThreshold));

1 个答案:

答案 0 :(得分:0)

感谢您的评论。

所以这个解决方案适用于Spark的Java实现。如果您想要实现Scala,请查看Jacek Laskowski的帖子。

解决方案:

//first convert the columns Size and Records to a List<Double>
List<Double> sizeList = dataFrame.select("Size").javaRDD().map(f -> f.getDouble(0)).collect();
List<Double> recordsList = dataFrame.select("Records").javaRDD().map(f -> f.getDouble(0)).collect();

//then convert the lists into JavaDoubleRDD
JavaDoubleRDD size = sparkContext.parallelizeDoubles(sizeList);
JavaDoubleRDD records = sparkContext.parallelizeDoubles(recordsList);

//calculate the mean and stddev using the built in functions:
double sizeMean = size.mean();
double sizeStdev = size.stdev();
double recordsMean = records.mean();
double recordsStdev = records.stdev();

之后我终于可以在Column比较函数中使用这些值。 希望你明白我的所作所为。