一、背景
最近在做分析时,一旦数据含有极端值,均值常常失效,对此,试图通过截尾均值解决此问题。
于是提出:在hive中新建一个UDAF(聚类函数),计算一组数值的截尾均值。
二、方案
参考percentile()函数MR计算逻辑,通过截尾比例计算出有效数据区间,对有效数据区间求均值。
三、实现
1.函数源码:UDAFTrimAvg.java
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.apache.hadoop.hive.ql.exec.Description;
import org.apache.hadoop.hive.ql.exec.UDAF;
import org.apache.hadoop.hive.ql.exec.UDAFEvaluator;
import org.apache.hadoop.hive.serde2.io.DoubleWritable;
import org.apache.hadoop.hive.shims.ShimLoader;
import org.apache.hadoop.io.LongWritable;
@Description(name = "trim_avg",
value = "_FUNC_(expr, pct) - Returns the trimmed mean of expr, expr should be integer, pc should be double (range: (0, 0.5)).")
public class UDAFTrimAvg extends UDAF {
private static final Comparator<LongWritable> COMPARATOR;
static {
COMPARATOR = ShimLoader.getHadoopShims().getLongComparator();
}
// 定义state类,收集中间聚合结果
public static class State {
private Map<LongWritable, LongWritable> counts; // key计数
private DoubleWritable pct; //单边截尾比例
}
// 重写compare方法, 比较两个key的大小
public static class MyComparator implements Comparator<Map.Entry<Lo