Repository: jtablesaw/tablesaw
Pull request #569 (2019-08-06 15:11:11)

Fix for Make it easier to work with missing data #564
plus test, plus fix for a bug in a DoubleColumn.create()

Thanks for contributing.

- [ ] Tick to sign-off your agreement to the [Developer Certificate of Origin (DCO) 1.1](https://developercertificate.org)

## Description

What was changed

## Testing

Did you add a unit test?


lwhite1: @ryancerf LMK if this works for your missing value issue #564 

Patch:
diff --git a/core/src/main/java/tech/tablesaw/api/BooleanColumn.java b/core/src/main/java/tech/tablesaw/api/BooleanColumn.java
index 19a10634..12e35676 100644
--- a/core/src/main/java/tech/tablesaw/api/BooleanColumn.java
+++ b/core/src/main/java/tech/tablesaw/api/BooleanColumn.java
@@ -289,7 +289,7 @@ public class BooleanColumn extends AbstractColumn<Boolean>
   @Override
   public BooleanColumn append(Boolean b) {
     if (b == null) {
-      data.add(BooleanColumnType.MISSING_VALUE);
+      appendMissing();
     } else if (b) {
       data.add(BooleanColumnType.BYTE_TRUE);
     } else {
diff --git a/core/src/main/java/tech/tablesaw/api/DoubleColumn.java b/core/src/main/java/tech/tablesaw/api/DoubleColumn.java
index b2a9b9e4..459e9287 100644
--- a/core/src/main/java/tech/tablesaw/api/DoubleColumn.java
+++ b/core/src/main/java/tech/tablesaw/api/DoubleColumn.java
@@ -109,19 +109,19 @@ public class DoubleColumn extends NumberColumn<Double> implements NumberFillers<
   }
 
   public static DoubleColumn create(final String name, final List<Number> numberList) {
-    final double[] doubles = new double[numberList.size()];
-    for (int i = 0; i < numberList.size(); i++) {
-      doubles[i] = numberList.get(i).doubleValue();
+    DoubleColumn newColumn = new DoubleColumn(name, new DoubleArrayList(0));
+    for (Number number : numberList) {
+        newColumn.append(number);
     }
-    return new DoubleColumn(name, new DoubleArrayList(doubles));
+    return newColumn;
   }
 
   public static DoubleColumn create(final String name, final Number[] numbers) {
-    final double[] doubles = new double[numbers.length];
-    for (int i = 0; i < numbers.length; i++) {
-      doubles[i] = numbers[i].doubleValue();
+    DoubleColumn newColumn = new DoubleColumn(name, new DoubleArrayList(0));
+    for (Number number : numbers) {
+        newColumn.append(number);
     }
-    return new DoubleColumn(name, new DoubleArrayList(doubles));
+    return newColumn;
   }
 
   public static DoubleColumn create(final String name, final int initialSize) {
@@ -241,12 +241,20 @@ public class DoubleColumn extends NumberColumn<Double> implements NumberFillers<
 
   @Override
   public DoubleColumn append(Double val) {
-    this.append(val.doubleValue());
+    if (val == null) {
+      appendMissing();
+    } else {
+      append(val.doubleValue());
+    }
     return this;
   }
 
-  public DoubleColumn append(Integer val) {
-    this.append(val.doubleValue());
+  public DoubleColumn append(Number val) {
+    if (val == null) {
+      appendMissing();
+    } else {
+      append(val.doubleValue());
+    }
     return this;
   }
 
diff --git a/core/src/main/java/tech/tablesaw/api/FloatColumn.java b/core/src/main/java/tech/tablesaw/api/FloatColumn.java
index d7c08701..fe78d503 100644
--- a/core/src/main/java/tech/tablesaw/api/FloatColumn.java
+++ b/core/src/main/java/tech/tablesaw/api/FloatColumn.java
@@ -171,7 +171,11 @@ public class FloatColumn extends NumberColumn<Float> {
   }
 
   public FloatColumn append(Float val) {
-    this.append(val.floatValue());
+    if (val == null) {
+      appendMissing();
+    } else {
+      append(val.floatValue());
+    }
     return this;
   }
 
diff --git a/core/src/main/java/tech/tablesaw/api/IntColumn.java b/core/src/main/java/tech/tablesaw/api/IntColumn.java
index de2e0496..61cbc550 100644
--- a/core/src/main/java/tech/tablesaw/api/IntColumn.java
+++ b/core/src/main/java/tech/tablesaw/api/IntColumn.java
@@ -46,6 +46,14 @@ public class IntColumn extends NumberColumn<Integer> implements CategoricalColum
     return new IntColumn(name, new IntArrayList(arr));
   }
 
+  public static IntColumn create(final String name, final Integer[] arr) {
+    IntColumn newColumn = IntColumn.create(name, 0);
+    for (Integer integer : arr) {
+        newColumn.append(integer);
+    }
+    return newColumn;
+  }
+
   public static IntColumn create(final String name, final int initialSize) {
     IntColumn column = new IntColumn(name, new IntArrayList(initialSize));
     for (int i = 0; i < initialSize; i++) {
@@ -184,7 +192,11 @@ public class IntColumn extends NumberColumn<Integer> implements CategoricalColum
   }
 
   public IntColumn append(Integer val) {
-    this.append(val.intValue());
+    if (val == null) {
+      appendMissing();
+    } else {
+      append(val.intValue());
+    }
     return this;
   }
 
diff --git a/core/src/main/java/tech/tablesaw/api/LongColumn.java b/core/src/main/java/tech/tablesaw/api/LongColumn.java
index cd857b5b..cfbf47a9 100644
--- a/core/src/main/java/tech/tablesaw/api/LongColumn.java
+++ b/core/src/main/java/tech/tablesaw/api/LongColumn.java
@@ -195,7 +195,11 @@ public class LongColumn extends NumberColumn<Long> implements CategoricalColumn<
   }
 
   public LongColumn append(Long val) {
-    this.append(val.longValue());
+    if (val == null) {
+      appendMissing();
+    } else {
+      append(val.longValue());
+    }
     return this;
   }
 
diff --git a/core/src/main/java/tech/tablesaw/api/ShortColumn.java b/core/src/main/java/tech/tablesaw/api/ShortColumn.java
index 72cb7d4f..cc9ea11d 100644
--- a/core/src/main/java/tech/tablesaw/api/ShortColumn.java
+++ b/core/src/main/java/tech/tablesaw/api/ShortColumn.java
@@ -173,7 +173,11 @@ public class ShortColumn extends NumberColumn<Short> implements CategoricalColum
   }
 
   public ShortColumn append(Short val) {
-    this.append(val.shortValue());
+    if (val == null) {
+      appendMissing();
+    } else {
+      append(val.shortValue());
+    }
     return this;
   }
 
diff --git a/core/src/main/java/tech/tablesaw/columns/Column.java b/core/src/main/java/tech/tablesaw/columns/Column.java
index fccbc9cf..a016b7e7 100644
--- a/core/src/main/java/tech/tablesaw/columns/Column.java
+++ b/core/src/main/java/tech/tablesaw/columns/Column.java
@@ -349,6 +349,20 @@ public interface Column<T> extends Iterable<T>, Comparator<T> {
 
   Column<T> setMissing(int i);
 
+  /**
+   * Sets the value of any missing data in the column to newValue and returns the same column
+   * @param newValue  the value to be used for all missing data in this column
+   * @return  the column updated
+   */
+  default Column<T> setMissingTo(T newValue) {
+    for (int i = 0; i < size(); i++) {
+      if (isMissing(i)) {
+        set(i, newValue);
+      }
+    }
+    return this;
+  }
+
   /**
    * Returns a new Column of the same type with only those rows satisfying the predicate
    *


Test patch:
diff --git a/core/src/test/java/tech/tablesaw/columns/ColumnTest.java b/core/src/test/java/tech/tablesaw/columns/ColumnTest.java
index 99095100..fd8c0510 100644
--- a/core/src/test/java/tech/tablesaw/columns/ColumnTest.java
+++ b/core/src/test/java/tech/tablesaw/columns/ColumnTest.java
@@ -30,6 +30,7 @@ import tech.tablesaw.api.ColumnType;
 import tech.tablesaw.api.DateColumn;
 import tech.tablesaw.api.DateTimeColumn;
 import tech.tablesaw.api.DoubleColumn;
+import tech.tablesaw.api.IntColumn;
 import tech.tablesaw.api.StringColumn;
 import tech.tablesaw.api.Table;
 import tech.tablesaw.io.csv.CsvReadOptions;
@@ -139,6 +140,31 @@ public class ColumnTest {
     assertTrue(dc3.contains(-1.0));
   }
 
+  @Test
+  public void testSetMissingTo() {
+    Double[] d1 = {1d, null, -1d};
+    Integer[] i1 = {2, null, 3};
+    String[] s1 = {"a", null, "C"};
+    LocalDate[] dt1 = {LocalDate.now(), null, LocalDate.now()};
+
+    DoubleColumn dc1 = DoubleColumn.create("t1", d1);
+    IntColumn ic1 = IntColumn.create("t2", i1);
+    StringColumn sc1 = StringColumn.create("t3", s1);
+    DateColumn dtc1 = DateColumn.create("t4", dt1);
+
+    dc1.setMissingTo(-34.2);
+    assertTrue(dc1.contains(-34.2));
+
+    ic1.setMissingTo(-34);
+    assertTrue(ic1.contains(-34));
+
+    sc1.setMissingTo("missing");
+    assertTrue(sc1.contains("missing"));
+
+    dtc1.setMissingTo(LocalDate.of(2001, 1, 1));
+    assertTrue(dtc1.contains(LocalDate.of(2001, 1, 1)));
+  }
+
   @Test
   public void testMax() {
     double[] d1 = {1, 0, -1};