diff --git a/core/src/main/java/tech/tablesaw/api/Table.java b/core/src/main/java/tech/tablesaw/api/Table.java index 06666b5e5..970e21353 100644 --- a/core/src/main/java/tech/tablesaw/api/Table.java +++ b/core/src/main/java/tech/tablesaw/api/Table.java @@ -457,19 +457,9 @@ public List columnNames() { return columnList.stream().map(Column::name).collect(toList()); } - /** Returns a table with the same columns as this table */ + /** Returns a table with the same columns and data as this table */ public Table copy() { - Table copy = new Table(name); - for (Column column : columnList) { - copy.addColumns(column.emptyCopy(rowCount())); - } - - int[] rows = new int[rowCount()]; - for (int i = 0; i < rowCount(); i++) { - rows[i] = i; - } - Rows.copyRowsToTable(rows, this, copy); - return copy; + return inRange(0, this.rowCount()); } /** Returns a table with the same columns as this table, but no data */ @@ -493,6 +483,57 @@ public Table emptyCopy(int rowSize) { return copy; } + /** + * Copies the rows specified by Selection into newTable + * + * @param rows A Selection defining the rows to copy + * @param newTable The table to copy the rows into + */ + @SuppressWarnings({"rawtypes", "unchecked"}) + public void copyRowsToTable(Selection rows, Table newTable) { + for (int columnIndex = 0; columnIndex < this.columnCount(); columnIndex++) { + Column oldColumn = this.column(columnIndex); + int r = 0; + for (int i : rows) { + newTable.column(columnIndex).set(r, oldColumn, i); + r++; + } + } + } + + /** + * Copies the rows indicated by the row index values in the given array from oldTable to newTable + */ + @SuppressWarnings({"rawtypes", "unchecked"}) + public void copyRowsToTable(int[] rows, Table newTable) { + for (int columnIndex = 0; columnIndex < columnCount(); columnIndex++) { + Column oldColumn = column(columnIndex); + int r = 0; + for (int i : rows) { + newTable.column(columnIndex).set(r, oldColumn, i); + r++; + } + } + } + + /** + * Returns {@code true} if the row @rowNumber in table1 holds the same data as the row at + * rowNumber in table2 + */ + public static boolean compareRows(int rowNumber, Table table1, Table table2) { + int columnCount = table1.columnCount(); + boolean result; + for (int columnIndex = 0; columnIndex < columnCount; columnIndex++) { + ColumnType columnType = table1.column(columnIndex).type(); + result = + columnType.compare(rowNumber, table2.column(columnIndex), table1.column(columnIndex)); + if (!result) { + return false; + } + } + return true; + } + /** * Splits the table into two, randomly assigning records to each according to the proportion given * in trainingProportion @@ -659,7 +700,7 @@ private Table sortOn(IntComparator rowComparator) { int[] newRows = rows(); IntArrays.mergeSort(newRows, rowComparator); - Rows.copyRowsToTable(newRows, this, newTable); + copyRowsToTable(newRows, newTable); return newTable; } @@ -772,7 +813,7 @@ public Table dropRange(int rowStart, int rowEnd) { /** Returns a table containing the rows contained in the given Selection */ public Table where(Selection selection) { Table newTable = this.emptyCopy(selection.size()); - Rows.copyRowsToTable(selection, this, newTable); + copyRowsToTable(selection, newTable); return newTable; } @@ -795,7 +836,7 @@ public Table dropWhere(Selection selection) { opposite.addRange(0, rowCount()); opposite.andNot(selection); Table newTable = this.emptyCopy(opposite.size()); - Rows.copyRowsToTable(opposite, this, newTable); + copyRowsToTable(opposite, newTable); return newTable; } @@ -868,8 +909,8 @@ public Table dropDuplicateRows() { Table temp = emptyCopy(); for (int row = 0; row < rowCount(); row++) { - if (temp.isEmpty() || !Rows.compareRows(row, sorted, temp)) { - Rows.appendRowToTable(row, sorted, temp); + if (temp.isEmpty() || !compareRows(row, sorted, temp)) { + temp.append(sorted.row(row)); } } return temp; @@ -892,7 +933,7 @@ public Table dropRowsWithMissingValues() { Selection notMissing = Selection.withRange(0, rowCount()); notMissing.andNot(missing); Table temp = emptyCopy(notMissing.size()); - Rows.copyRowsToTable(notMissing, this, temp); + copyRowsToTable(notMissing, temp); return temp; } diff --git a/core/src/main/java/tech/tablesaw/table/RollingColumn.java b/core/src/main/java/tech/tablesaw/table/RollingColumn.java index c59bcde41..4c24d8b84 100644 --- a/core/src/main/java/tech/tablesaw/table/RollingColumn.java +++ b/core/src/main/java/tech/tablesaw/table/RollingColumn.java @@ -9,24 +9,30 @@ /** Does a calculation on a rolling basis (e.g. mean for last 20 days) */ public class RollingColumn { + /** The column providing the data for the rolling calculation */ protected final Column column; + + /** The size of the rolling window */ protected final int window; + /** + * Constructs a rolling column based on calculations on a sliding window of {@code window} rows of + * data from the given column + */ public RollingColumn(Column column, int window) { this.column = column; this.window = window; } + /** + * Generates a name for the column based on the name of the original column and the function used + * in the calculation + */ protected String generateNewColumnName(AggregateFunction function) { - return new StringBuilder(column.name()) - .append(" ") - .append(window) - .append("-period") - .append(" ") - .append(function.functionName()) - .toString(); + return column.name() + " " + window + "-period" + " " + function.functionName(); } + /** Performs the calculation and returns a new column containing the results */ @SuppressWarnings({"unchecked"}) public , OUT> Column calc(AggregateFunction function) { // TODO: the subset operation copies the array. creating a view would likely be more efficient diff --git a/core/src/main/java/tech/tablesaw/table/Rows.java b/core/src/main/java/tech/tablesaw/table/Rows.java index 3f9d5e9ef..377d672bd 100644 --- a/core/src/main/java/tech/tablesaw/table/Rows.java +++ b/core/src/main/java/tech/tablesaw/table/Rows.java @@ -21,8 +21,14 @@ import tech.tablesaw.selection.BitmapBackedSelection; import tech.tablesaw.selection.Selection; -/** A static utility class for row operations */ +/** + * A static utility class for row operations + * + * @deprecated Functionality provided by this class is methods in the {@link Table} class hierarchy, + * and/or by methods in {@link tech.tablesaw.api.Row} + */ @Immutable +@Deprecated public final class Rows { // Don't instantiate @@ -31,7 +37,10 @@ private Rows() {} /** * Copies the rows indicated by the row index values in the given selection from oldTable to * newTable + * + * @deprecated Use the instance method {Table:where(Selection} instead */ + @Deprecated @SuppressWarnings({"rawtypes", "unchecked"}) public static void copyRowsToTable(Selection rows, Table oldTable, Table newTable) { for (int columnIndex = 0; columnIndex < oldTable.columnCount(); columnIndex++) { @@ -46,7 +55,10 @@ public static void copyRowsToTable(Selection rows, Table oldTable, Table newTabl /** * Copies the rows indicated by the row index values in the given array from oldTable to newTable + * + * @deprecated Use the instance method {@link Table:copyRowsToTable()} instead */ + @Deprecated @SuppressWarnings({"rawtypes", "unchecked"}) public static void copyRowsToTable(int[] rows, Table oldTable, Table newTable) { for (int columnIndex = 0; columnIndex < oldTable.columnCount(); columnIndex++) { @@ -59,6 +71,12 @@ public static void copyRowsToTable(int[] rows, Table oldTable, Table newTable) { } } + /** + * Appends a row from oldTable to newTable + * + * @deprecated Use the instance method {@link Table:appendRow(Row)} instead + */ + @Deprecated @SuppressWarnings({"rawtypes", "unchecked"}) public static void appendRowToTable(int row, Table oldTable, Table newTable) { int[] rows = new int[] {row}; @@ -70,6 +88,8 @@ public static void appendRowToTable(int row, Table oldTable, Table newTable) { } } + /** @deprecated Use the static method {@link Table:compareRows()} instead */ + @Deprecated public static boolean compareRows(int rowInOriginal, Table original, Table tempTable) { int columnCount = original.columnCount(); boolean result; @@ -85,6 +105,12 @@ public static boolean compareRows(int rowInOriginal, Table original, Table tempT return true; } + /** + * Copies the first n rows to a new table + * + * @deprecated Use {@link Table:first()} instead + */ + @Deprecated public static void head(int rowCount, Table oldTable, Table newTable) { Selection rows = new BitmapBackedSelection(rowCount); for (int i = 0; i < rowCount; i++) { @@ -93,6 +119,12 @@ public static void head(int rowCount, Table oldTable, Table newTable) { copyRowsToTable(rows, oldTable, newTable); } + /** + * Copies the last n rows to a new table + * + * @deprecated Use {@link Table:last()} instead + */ + @Deprecated public static void tail(int rowsToInclude, Table oldTable, Table newTable) { int oldTableSize = oldTable.rowCount(); int start = oldTableSize - rowsToInclude; diff --git a/core/src/main/java/tech/tablesaw/table/SelectionTableSliceGroup.java b/core/src/main/java/tech/tablesaw/table/SelectionTableSliceGroup.java index e8151eabb..3196e1305 100644 --- a/core/src/main/java/tech/tablesaw/table/SelectionTableSliceGroup.java +++ b/core/src/main/java/tech/tablesaw/table/SelectionTableSliceGroup.java @@ -23,6 +23,16 @@ /** A group of tables formed by performing splitting operations on an original table */ public class SelectionTableSliceGroup extends TableSliceGroup { + /** + * Creates a TableSliceGroup where each slice contains {@code step} number of rows from the + * backing table + * + * @param original The original backing table that provides the data for the new slice group + * @param subTableNameTemplate The prefix of a name for each slice in the group. If the argument + * is "step" the name will take the form "step 1", "step 2", etc. + * @param step The number of rows per slice + * @return The new table + */ public static SelectionTableSliceGroup create( Table original, String subTableNameTemplate, int step) { return new SelectionTableSliceGroup(original, subTableNameTemplate, step); diff --git a/core/src/main/java/tech/tablesaw/table/StandardTableSliceGroup.java b/core/src/main/java/tech/tablesaw/table/StandardTableSliceGroup.java index d59073462..f649b5268 100644 --- a/core/src/main/java/tech/tablesaw/table/StandardTableSliceGroup.java +++ b/core/src/main/java/tech/tablesaw/table/StandardTableSliceGroup.java @@ -32,6 +32,11 @@ /** A group of tables formed by performing splitting operations on an original table */ public class StandardTableSliceGroup extends TableSliceGroup { + /** + * Constructs a TableSliceGroup made by subdividing the original table by the given columns. A + * group subdividing on the two columns "Name" and "Place" will have a slice for every combination + * of name and place in the table + */ private StandardTableSliceGroup(Table original, CategoricalColumn... columns) { super(original, splitColumnNames(columns)); setSourceTable(getSourceTable()); diff --git a/core/src/main/java/tech/tablesaw/table/TableSlice.java b/core/src/main/java/tech/tablesaw/table/TableSlice.java index ba274e162..f758f52c5 100644 --- a/core/src/main/java/tech/tablesaw/table/TableSlice.java +++ b/core/src/main/java/tech/tablesaw/table/TableSlice.java @@ -42,9 +42,16 @@ */ public class TableSlice extends Relation { + /** The physical table object backing this slice */ private final Table table; + + /** The name of the slice */ private String name; + + /** The Selection that defines which rows in the table are present in this slice */ @Nullable private Selection selection; + + /** An array of row indices defining the presentation order of the slice */ @Nullable private int[] sortOrder = null; /** @@ -67,6 +74,7 @@ public TableSlice(Table table) { this.table = table; } + /** {@inheritDoc} */ @Override public Column column(int columnIndex) { Column col = table.column(columnIndex); @@ -78,16 +86,19 @@ public Column column(int columnIndex) { return col; } + /** {@inheritDoc} */ @Override public Column column(String columnName) { return column(table.columnIndex(columnName)); } + /** {@inheritDoc} */ @Override public int columnCount() { return table.columnCount(); } + /** {@inheritDoc} */ @Override public int rowCount() { if (hasSelection()) { @@ -96,6 +107,7 @@ public int rowCount() { return table.rowCount(); } + /** {@inheritDoc} */ @Override public List> columns() { List> columns = new ArrayList<>(); @@ -105,21 +117,25 @@ public List> columns() { return columns; } + /** {@inheritDoc} */ @Override public int columnIndex(Column column) { return table.columnIndex(column); } + /** {@inheritDoc} */ @Override public Object get(int r, int c) { return table.get(mappedRowNumber(r), c); } + /** {@inheritDoc} */ @Override public String name() { return name; } + /** {@inheritDoc} */ public Table getTable() { return table; } @@ -144,23 +160,27 @@ public void removeSelection() { this.selection = null; } + /** {@inheritDoc} */ @Override public List columnNames() { return table.columnNames(); } + /** {@inheritDoc} */ @Override public TableSlice addColumns(Column... column) { throw new UnsupportedOperationException( "Class TableSlice does not support the addColumns operation"); } + /** {@inheritDoc} */ @Override public TableSlice removeColumns(Column... columns) { throw new UnsupportedOperationException( "Class TableSlice does not support the removeColumns operation"); } + /** {@inheritDoc} */ @Override public Table first(int nRows) { int count = 0; @@ -174,12 +194,14 @@ public Table first(int nRows) { return copy; } + /** {@inheritDoc} */ @Override public TableSlice setName(String name) { this.name = name; return this; } + /** Returns the data in this slice as a new Table */ public Table asTable() { Table table = Table.create(this.name()); for (Column column : this.columns()) { diff --git a/core/src/main/java/tech/tablesaw/table/TableSliceGroup.java b/core/src/main/java/tech/tablesaw/table/TableSliceGroup.java index b8601c21b..a6f8fc5a1 100644 --- a/core/src/main/java/tech/tablesaw/table/TableSliceGroup.java +++ b/core/src/main/java/tech/tablesaw/table/TableSliceGroup.java @@ -29,20 +29,28 @@ import tech.tablesaw.api.Table; import tech.tablesaw.columns.Column; -/** A group of tables formed by performing splitting operations on an original table */ -public class TableSliceGroup implements Iterable { +/** + * A group of virtual tables (table slices) formed by performing splitting operations on an original + * table See: {@link TableSlice} + */ +public abstract class TableSliceGroup implements Iterable { - // A string that is used internally as a delimiter in creating a column name from all the grouping - // columns + /** + * A string that is used internally as a delimiter in creating a column name from all the grouping + * columns + */ protected static final String SPLIT_STRING = "~~~"; - // A function that splits the group column name back into the original column names for the - // grouping columns + /** + * A function that splits the group column name back into the original column names for the + * grouping columns + */ private static final Splitter SPLITTER = Splitter.on(SPLIT_STRING); - // The list of slices or views over the source table that I contain + /** The list of slices or views over the source table that I contain */ private final List subTables = new ArrayList<>(); + /** An array containing the names of the columns that the backing table was split on */ private final String[] splitColumnNames; // The table that underlies all the manipulations performed here @@ -65,10 +73,12 @@ protected TableSliceGroup(Table sourceTable, String[] groupColumnNames) { this.splitColumnNames = groupColumnNames; } + /** Returns the names of the columns the backing table was split on. */ protected String[] getSplitColumnNames() { return splitColumnNames; } + /** Returns the sum of the sizes for the columns in the given {@link Column} list */ protected int getByteSize(List> columns) { int byteSize = 0; for (Column c : columns) { @@ -77,18 +87,22 @@ protected int getByteSize(List> columns) { return byteSize; } + /** Add a slice to this group */ protected void addSlice(TableSlice slice) { subTables.add(slice); } + /** Returns the slices as a list */ public List getSlices() { return subTables; } + /** Returns the ith slice in this group */ public TableSlice get(int i) { return subTables.get(i); } + /** Returns the table behind this slice group */ public Table getSourceTable() { return sourceTable; } @@ -177,6 +191,7 @@ public Table aggregate(ListMultimap> functions) return splitGroupingColumn(groupTable); } + /** Returns the name of a summary table made by aggregating on the slices in this group */ public static Table summaryTableName(Table source) { return Table.create(source.name() + " summary"); } @@ -209,6 +224,7 @@ public List asTableList() { return tableList; } + /** Sets the source table that backs this TableSliceGroup */ protected void setSourceTable(Table sourceTable) { this.sourceTable = sourceTable; }