You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@knox.apache.org by kr...@apache.org on 2019/10/16 13:19:20 UTC

[knox] branch master updated: KNOX-2052 - KnoxShellTable mean, median, and mode methods (#163)

This is an automated email from the ASF dual-hosted git repository.

krisden pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/knox.git


The following commit(s) were added to refs/heads/master by this push:
     new 04f5d86  KNOX-2052 - KnoxShellTable mean, median, and mode methods (#163)
04f5d86 is described below

commit 04f5d86a0caa466755d287827e2b783f5896099f
Author: Larry McCay IV <46...@users.noreply.github.com>
AuthorDate: Wed Oct 16 09:19:12 2019 -0400

    KNOX-2052 - KnoxShellTable mean, median, and mode methods (#163)
---
 gateway-shell/pom.xml                              |   4 +
 .../knox/gateway/shell/table/KnoxShellTable.java   | 179 ++++++++++++++++++++-
 .../gateway/shell/table/KnoxShellTableTest.java    | 150 +++++++++++++++++
 pom.xml                                            |   6 +
 4 files changed, 337 insertions(+), 2 deletions(-)

diff --git a/gateway-shell/pom.xml b/gateway-shell/pom.xml
index 61e61d4..4f57b71 100644
--- a/gateway-shell/pom.xml
+++ b/gateway-shell/pom.xml
@@ -95,6 +95,10 @@
             <artifactId>commons-lang3</artifactId>
         </dependency>
         <dependency>
+            <groupId>org.apache.commons</groupId>
+            <artifactId>commons-math3</artifactId>
+        </dependency>
+        <dependency>
             <groupId>commons-io</groupId>
             <artifactId>commons-io</artifactId>
         </dependency>
diff --git a/gateway-shell/src/main/java/org/apache/knox/gateway/shell/table/KnoxShellTable.java b/gateway-shell/src/main/java/org/apache/knox/gateway/shell/table/KnoxShellTable.java
index 00b47cc..0f8da20 100644
--- a/gateway-shell/src/main/java/org/apache/knox/gateway/shell/table/KnoxShellTable.java
+++ b/gateway-shell/src/main/java/org/apache/knox/gateway/shell/table/KnoxShellTable.java
@@ -24,8 +24,8 @@ import java.util.concurrent.ThreadLocalRandom;
 import java.util.concurrent.atomic.AtomicInteger;
 
 import javax.swing.SortOrder;
-
 import com.fasterxml.jackson.annotation.JsonFilter;
+import org.apache.commons.math3.stat.StatUtils;
 
 
 /**
@@ -35,6 +35,16 @@ import com.fasterxml.jackson.annotation.JsonFilter;
  */
 @JsonFilter("knoxShellTableFilter")
 public class KnoxShellTable {
+
+    private enum Conversions {
+        DOUBLE,
+        INTEGER,
+        FLOAT,
+        BYTE,
+        SHORT,
+        LONG
+    }
+
   private static final String LINE_SEPARATOR = System.getProperty("line.separator");
 
   List<String> headers = new ArrayList<String>();
@@ -86,6 +96,172 @@ public class KnoxShellTable {
     return col;
   }
 
+  private Conversions getConversion(Comparable<? extends Object> colIndex) {
+      Conversions type = null;
+      if (colIndex instanceof Double) {
+        type = Conversions.DOUBLE;
+      }
+      else if (colIndex instanceof Integer) {
+        type = Conversions.INTEGER;
+      }
+      else if (colIndex instanceof Float) {
+        type = Conversions.FLOAT;
+      }
+      else if (colIndex instanceof Byte) {
+        type = Conversions.BYTE;
+      }
+      else if (colIndex instanceof Short) {
+        type = Conversions.SHORT;
+      }
+      else if (colIndex instanceof Long) {
+        type = Conversions.LONG;
+      }
+      else {
+          throw new IllegalArgumentException();
+      }
+      return type;
+  }
+
+  private double[] toDoubleArray(String colName) throws IllegalArgumentException {
+    List<Comparable<? extends Object>> col = values(colName);
+    double[] colArray = new double[col.size()];
+    Conversions conversionMethod = null;
+    for (int i = 0; i < col.size(); i++) {
+      if (i == 0) {
+        conversionMethod = getConversion(col.get(i));
+      }
+      switch (conversionMethod) {
+        case DOUBLE:
+          colArray[i] = (double) ((Double) col.get(i));
+          break;
+        case INTEGER:
+          colArray[i] = (double) ((Integer) col.get(i)).intValue();
+          break;
+        case FLOAT:
+          colArray[i] = (double) ((Float) col.get(i)).floatValue();
+          break;
+        case BYTE:
+          colArray[i] = (double) ((Byte) col.get(i)).byteValue();
+          break;
+        case SHORT:
+          colArray[i] = (double) ((Short) col.get(i)).shortValue();
+          break;
+        case LONG:
+          colArray[i] = (double) ((Long) col.get(i)).longValue();
+          break;
+      }
+    }
+    return colArray;
+  }
+
+  /**
+   * Calculates the mean of specified column
+   * @param colName
+   * @return mean
+   */
+  public double mean(String colName) {
+    return StatUtils.mean(toDoubleArray(colName));
+  }
+
+  /**
+   * Calculates the mean of specified column
+   * @param colName
+   * @return mean
+   */
+  public double mean(int colIndex) {
+    return mean(headers.get(colIndex));
+  }
+
+  /**
+   * Calculates the median of specified column
+   * @param colName
+   * @return median
+   */
+  public double median(String colName) {
+    return StatUtils.percentile(toDoubleArray(colName), 50);
+  }
+
+  /**
+   * Calculates the median of specified column
+   * @param colName
+   * @return median
+   */
+  public double median(int colIndex) {
+    return median(headers.get(colIndex));
+  }
+
+  /**
+   * Calculates the mode of specified column
+   * @param colName
+   * @return mode
+   */
+  public double mode(String colName) {
+    return (double) StatUtils.mode(toDoubleArray(colName))[0];
+  }
+
+  /**
+   * Calculates the mode of specified column
+   * @param colName
+   * @return mode
+   */
+  public double mode(int colIndex) {
+    return mode(headers.get(colIndex));
+  }
+
+  /**
+   * Calculates the sum of specified column
+   * @param colName
+   * @return sum
+   */
+  public double sum(String colName) {
+    return StatUtils.sum(toDoubleArray(colName));
+  }
+
+  /**
+   * Calculates the sum of specified column
+   * @param colName
+   * @return sum
+   */
+  public double sum(int colIndex) {
+    return sum(headers.get(colIndex));
+  }
+
+  /**
+   * Calculates the max of specified column
+   * @param colName
+   * @return max
+   */
+  public double max(String colName) {
+    return StatUtils.max(toDoubleArray(colName));
+  }
+
+  /**
+   * Calculates the max of specified column
+   * @param colName
+   * @return max
+   */
+  public double max(int colIndex) {
+    return max(headers.get(colIndex));
+  }
+
+  /**
+   * Calculates the min of specified column
+   * @param colName
+   * @return min
+   */
+  public double min(String colName) {
+    return StatUtils.min(toDoubleArray(colName));
+  }
+
+  /**
+   * Calculates the min of specified column
+   * @param colName
+   * @return min
+   */
+  public double min(int colIndex) {
+    return min(headers.get(colIndex));
+  }
+
   public KnoxShellTable apply(KnoxShellTableCell<? extends Comparable<? extends Object>> cell) {
     if (!headers.isEmpty()) {
       headers.set(cell.colIndex, cell.header);
@@ -234,5 +410,4 @@ public class KnoxShellTable {
   public String toCSV() {
     return new KnoxShellTableRenderer(this).toCSV();
   }
-
 }
diff --git a/gateway-shell/src/test/java/org/apache/knox/gateway/shell/table/KnoxShellTableTest.java b/gateway-shell/src/test/java/org/apache/knox/gateway/shell/table/KnoxShellTableTest.java
index efb618f..65d7f4c 100644
--- a/gateway-shell/src/test/java/org/apache/knox/gateway/shell/table/KnoxShellTableTest.java
+++ b/gateway-shell/src/test/java/org/apache/knox/gateway/shell/table/KnoxShellTableTest.java
@@ -359,6 +359,156 @@ public class KnoxShellTableTest {
     verify(connection, statement, resultSet, metadata);
   }
 
+  @Test (expected = IllegalArgumentException.class)
+  public void testConversion() throws IllegalArgumentException {
+      KnoxShellTable TABLE = new KnoxShellTable();
+      TABLE.header("Column Integer").header("Column String").header("Column Null");
+      TABLE.row().value(10).value("John").value(null);
+
+      System.out.println(TABLE.mean("Column String"));
+      System.out.println(TABLE.mean("Column Null"));
+
+  }
+
+  @Test
+  public void testMean() throws Exception {
+
+      Byte byte10 = 10;
+      Byte byte20 = 20;
+      Byte byte30 = 30;
+
+      Short short10 = 10;
+      Short short20 = 20;
+      Short short30 = 30;
+
+      Long long10 = (long) 100000000;
+      Long long20 = (long) 200000000;
+      Long long30 = (long) 300000000;
+
+      KnoxShellTable TABLE = new KnoxShellTable();
+      TABLE.header("Column Integer").header("Column Double").header("Column Float").header("Column Byte").header("Column Short").header("Column Long");
+      TABLE.row().value(10).value(20d).value(20.9999).value(byte10).value(short10).value(long10);
+      TABLE.row().value(30).value(40d).value(40.9999).value(byte20).value(short20).value(long20);
+      TABLE.row().value(27).value(60d).value(60.9999).value(byte30).value(short30).value(long30);
+
+      assertEquals(22.3, TABLE.mean("Column Integer"), 0.1);
+      assertEquals(40, TABLE.mean("Column Double"), 0.1);
+      assertEquals(22.3, TABLE.mean(0), 0.1);
+      assertEquals(40, TABLE.mean(1), 0.1);
+      assertEquals(40.9999, TABLE.mean("Column Float"), 0.1);
+      assertEquals(40.9999, TABLE.mean(2), 0.1);
+      assertEquals(20, TABLE.mean("Column Byte"), 0.1);
+      assertEquals(20, TABLE.mean("Column Short"), 0.1);
+      assertEquals(2.0E8, TABLE.mean("Column Long"), 0.1);
+  }
+
+  @Test
+  public void testMedian() throws Exception {
+
+      KnoxShellTable TABLE = new KnoxShellTable();
+      TABLE.header("Column Integer").header("Column Double").header("Column Float");
+      TABLE.row().value(10).value(20d).value(40.9999);
+      assertEquals(10, TABLE.median("Column Integer"), 0.1);
+      assertEquals(10, TABLE.median(0), 0.1);
+      assertEquals(20, TABLE.median("Column Double"), 0.1);
+      assertEquals(20, TABLE.median(1), 0.1);
+      assertEquals(40.9999, TABLE.mean("Column Float"), 0.1);
+      assertEquals(40.9999, TABLE.mean(2), 0.1);
+
+      KnoxShellTable TABLE2 = new KnoxShellTable();
+      TABLE2.header("Column Integer").header("Column Double").header("Column Float");
+      TABLE2.row().value(10).value(20d).value(20.9999);
+      TABLE2.row().value(30).value(40d).value(40.9999);
+      TABLE2.row().value(50).value(41d).value(60.9999);
+      assertEquals(30, TABLE2.median("Column Integer"), 0.1);
+      assertEquals(30, TABLE2.median(0), 0.1);
+      assertEquals(40.9999, TABLE2.mean("Column Float"), 0.1);
+      assertEquals(40.9999, TABLE2.mean(2), 0.1);
+
+      KnoxShellTable TABLE3 = new KnoxShellTable();
+      TABLE3.header("Column Integer").header("Column Double").header("Column Float");
+      TABLE3.row().value(10).value(20d).value(0.0000);
+      TABLE3.row().value(30).value(40d).value(30.0000);
+      TABLE3.row().value(31).value(41d).value(31.0000);
+      TABLE3.row().value(50).value(60d).value(70.0000);
+      assertEquals(30.5, TABLE3.median("Column Integer"), 0.1);
+      assertEquals(30.5, TABLE3.median(0), 0.01);
+      assertEquals(40.5, TABLE3.median("Column Double"), 0.01);
+      assertEquals(40.5, TABLE3.median(1), 0.01);
+      assertEquals(30.5000, TABLE3.median("Column Float"), 0.1);
+      assertEquals(30.5000, TABLE3.median(2), 0.1);
+  }
+
+  @Test
+  public void testMode() throws Exception {
+
+      KnoxShellTable TABLE = new KnoxShellTable();
+      TABLE.header("Column Integer").header("Column Double").header("Column Float");
+      TABLE.row().value(10).value(20d).value(40.9999);
+      assertEquals(10, TABLE.mode("Column Integer"), 0.1);
+      assertEquals(10, TABLE.mode(0), 0.1);
+      assertEquals(40.9999, TABLE.mean("Column Float"), 0.1);
+      assertEquals(40.9999, TABLE.mean(2), 0.1);
+
+
+      KnoxShellTable TABLE2 = new KnoxShellTable();
+      TABLE2.header("Column Integer").header("Column Double").header("Column Float");
+      TABLE2.row().value(10).value(20d).value(20.9999);
+      TABLE2.row().value(30).value(40d).value(20.9999);
+      TABLE2.row().value(30).value(40d).value(30.9999);
+      assertEquals(30, TABLE2.median("Column Integer"), 0.1);
+      assertEquals(30, TABLE2.median(0), 0.1);
+      assertEquals(40, TABLE2.median("Column Double"), 0.1);
+      assertEquals(40, TABLE2.median(1), 0.1);
+      assertEquals(20.9999, TABLE2.median("Column Float"), 0.1);
+      assertEquals(20.9999, TABLE2.median(2), 0.1);
+  }
+
+  @Test
+  public void testSum() throws Exception {
+
+      KnoxShellTable TABLE = new KnoxShellTable();
+      TABLE.header("Column Integer").header("Column Double").header("Column Float");
+      TABLE.row().value(10).value(20d).value(20.5000);
+      TABLE.row().value(90).value(100d).value(20.0500);
+      assertEquals(100, TABLE.sum("Column Integer"), 0.1);
+      assertEquals(100, TABLE.sum(0), 0.1);
+      assertEquals(120, TABLE.sum("Column Double"), 0.1);
+      assertEquals(120, TABLE.sum(1), 0.1);
+      assertEquals(40.5500, TABLE.sum("Column Float"), 0.1);
+      assertEquals(40.5500, TABLE.sum(2), 0.1);
+  }
+
+  @Test
+  public void testMax() throws Exception {
+
+      KnoxShellTable TABLE = new KnoxShellTable();
+      TABLE.header("Column Integer").header("Column Double").header("Column Float");
+      TABLE.row().value(10).value(20d).value(30.9998);
+      TABLE.row().value(20).value(50d).value(30.9999);
+      assertEquals(20, TABLE.max("Column Integer"), 0.1);
+      assertEquals(20, TABLE.max(0), 0.1);
+      assertEquals(50, TABLE.max("Column Double"), 0.1);
+      assertEquals(50, TABLE.max(1), 0.1);
+      assertEquals(30.9999, TABLE.max("Column Float"), 0.1);
+      assertEquals(30.9999, TABLE.max(2), 0.1);
+  }
+
+  @Test
+  public void testMin() throws Exception {
+
+      KnoxShellTable TABLE = new KnoxShellTable();
+      TABLE.header("Column Integer").header("Column Double").header("Column Float");
+      TABLE.row().value(10).value(20d).value(20.9998);
+      TABLE.row().value(20).value(50d).value(20.9999);
+      assertEquals(10, TABLE.min("Column Integer"), 0.1);
+      assertEquals(10, TABLE.min(0), 0.1);
+      assertEquals(20, TABLE.min("Column Double"), 0.1);
+      assertEquals(20, TABLE.min(1), 0.1);
+      assertEquals(20.9998, TABLE.min("Column Float"), 0.1);
+      assertEquals(20.9998, TABLE.min(2), 0.1);
+  }
+
   @Test
   public void shouldReturnDifferentCallHistoryForDifferentTables() throws Exception {
     final KnoxShellTable table1 = new KnoxShellTable();
diff --git a/pom.xml b/pom.xml
index ea91d30..c0ef103 100644
--- a/pom.xml
+++ b/pom.xml
@@ -166,6 +166,7 @@
         <commons-digester3.version>3.2</commons-digester3.version>
         <commons-io.version>2.6</commons-io.version>
         <commons-lang3.version>3.9</commons-lang3.version>
+        <commons-math3.version>3.6.1</commons-math3.version>
         <commons-net.version>3.6</commons-net.version>
         <commons-text.version>1.8</commons-text.version>
         <cors-filter.version>2.8</cors-filter.version>
@@ -1544,6 +1545,11 @@
                 <version>${commons-lang3.version}</version>
             </dependency>
             <dependency>
+                <groupId>org.apache.commons</groupId>
+                <artifactId>commons-math3</artifactId>
+                <version>${commons-math3.version}</version>
+            </dependency>
+            <dependency>
                 <groupId>commons-net</groupId>
                 <artifactId>commons-net</artifactId>
                 <version>${commons-net.version}</version>