Winsorizer { public List<double[]> process(List<double[]> metrics) { int n = metrics.size(); int k = metrics.get(0).length; Percentile p = new Percentile(); bounds = new double[k][2]; List<double[]> newMetrics = new ArrayList<>(n); for (int i = 0; i < n; i++) { newMetrics.add(new double[k]); } double[] curDimensionValues = new double[n]; for (int j = 0; j < k; j++) { for (int i = 0; i < n; i++) { curDimensionValues[i] = metrics.get(i)[j]; } p.setData(curDimensionValues); bounds[j][0] = p.evaluate(trimPct); bounds[j][1] = p.evaluate(100 - trimPct); for (int i = 0; i < n; i++) { double curValue = curDimensionValues[i]; if (curValue > bounds[j][1]) { newMetrics.get(i)[j] = bounds[j][1]; } else if (curValue < bounds[j][0]) { newMetrics.get(i)[j] = bounds[j][0]; } else { newMetrics.get(i)[j] = curValue; } } } return newMetrics; } Winsorizer(double trimPct); List<double[]> process(List<double[]> metrics); public double trimPct; public double[][] bounds; }
@Test public void testTrimOutlier() { int n = 10; int k = 2; List<double[]> metrics = new ArrayList<double[]>(n); for (int i = 0; i < n; i++) { double[] curVec = new double[k]; for (int j = 0; j < k; j++) { curVec[j] = (double)i; } metrics.add(curVec); } metrics.get(5)[0] = 1e5; metrics.get(5)[1] = -0.24; Winsorizer trimmer = new Winsorizer(20); List<double[]> trimmed = trimmer.process(metrics); for (int i = 0; i < n; i++) { double[] curRow = trimmed.get(i); double[] origRow = metrics.get(i); for (int j = 0; j < curRow.length; j++) { if (curRow[j] < trimmer.bounds[j][1] && curRow[j] > trimmer.bounds[j][0]) { assertEquals(curRow[j], origRow[j], 0); } else { assertTrue(curRow[j] >= trimmer.bounds[j][0] && curRow[j] <= trimmer.bounds[j][1]); } } } }