All Downloads are FREE. Search and download functionalities are using the official Maven repository.

tech.tablesaw.table.TableSlice Maven / Gradle / Ivy

The newest version!
/*
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package tech.tablesaw.table;

import com.google.common.base.Preconditions;
import it.unimi.dsi.fastutil.ints.IntArrays;
import it.unimi.dsi.fastutil.ints.IntComparator;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
import java.util.PrimitiveIterator;
import java.util.stream.IntStream;
import javax.annotation.Nullable;
import tech.tablesaw.aggregate.NumericAggregateFunction;
import tech.tablesaw.api.NumericColumn;
import tech.tablesaw.api.Row;
import tech.tablesaw.api.Table;
import tech.tablesaw.columns.Column;
import tech.tablesaw.selection.Selection;
import tech.tablesaw.sorting.Sort;
import tech.tablesaw.sorting.SortUtils;
import tech.tablesaw.sorting.comparators.IntComparatorChain;

/**
 * A TableSlice is a facade around a Relation that acts as a filter. Requests for data are forwarded
 * to the underlying table. A TableSlice can be sorted independently of the underlying table.
 *
 * 

A TableSlice is only good until the structure of the underlying table changes. */ 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; /** * Returns a new View constructed from the given table, containing only the rows represented by * the bitmap */ public TableSlice(Table table, Selection rowSelection) { this.name = table.name(); this.selection = rowSelection; this.table = table; } /** * Returns a new view constructed from the given table. The view can be sorted independently of * the table. */ public TableSlice(Table table) { this.name = table.name(); this.selection = null; this.table = table; } /** {@inheritDoc} */ @Override public Column column(int columnIndex) { Column col = table.column(columnIndex); if (isSorted()) { return col.subset(sortOrder); } else if (hasSelection()) { return col.where(selection); } 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()) { return selection.size(); } return table.rowCount(); } /** {@inheritDoc} */ @Override public List> columns() { List> columns = new ArrayList<>(); for (int i = 0; i < columnCount(); i++) { columns.add(column(i)); } 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; } /** Returns the backing table for this slice */ public Table getTable() { return table; } /** Clears all rows from this View, leaving the structure in place */ @Override public void clear() { sortOrder = null; selection = Selection.with(); } /** Removes the sort from this View. */ public void removeSort() { this.sortOrder = null; } /** * Removes the selection from this view, leaving it with the same number of rows as the underlying * source table. */ 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; PrimitiveIterator.OfInt it = sourceRowNumberIterator(); Table copy = table.emptyCopy(); while (it.hasNext() && count < nRows) { int row = it.nextInt(); copy.addRow(table.row(row)); count++; } 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()) { table.addColumns(column); } return table; } /** * IntIterator of source table row numbers that are present in this view. This can be used to in * combination with the source table to iterate over the cells of a column in a sorted order * without copying the column. * * @return an int iterator of row numbers in the source table that are present in this view. */ protected PrimitiveIterator.OfInt sourceRowNumberIterator() { if (this.isSorted()) { return Arrays.stream(sortOrder).iterator(); } else if (this.hasSelection()) { return selection.iterator(); } return Selection.withRange(0, table.rowCount()).iterator(); } /** * Returns the result of applying the given function to the specified column * * @param numberColumnName The name of a numeric column in this table * @param function A numeric reduce function * @return the function result * @throws IllegalArgumentException if numberColumnName doesn't name a numeric column in this * table */ public double reduce(String numberColumnName, NumericAggregateFunction function) { NumericColumn column = table.numberColumn(numberColumnName); if (hasSelection()) { return function.summarize(column.where(selection)); } return function.summarize(column); } /** * Iterate over the underlying rows in the source table. If you set one of the rows while * iterating it will change the row in the source table. */ @Override public Iterator iterator() { return new Iterator() { private final Row row = new Row(TableSlice.this); @Override public Row next() { return row.next(); } @Override public boolean hasNext() { return row.hasNext(); } }; } private boolean hasSelection() { return selection != null; } private boolean isSorted() { return sortOrder != null; } /** * Maps the view row number to the row number on the underlying source table. * * @param rowNumber the row number in the view. * @return the matching row number in the underlying table. */ public int mappedRowNumber(int rowNumber) { if (isSorted()) { return sortOrder[rowNumber]; } else if (hasSelection()) { return selection.get(rowNumber); } return rowNumber; } /** * Sort this view in place without modifying or copying the underlying source table. Unlike {@link * Table#sortOn(Sort)} which returns a copy of the table, this method sorts the view in place. * * @param key to sort on. */ public void sortOn(Sort key) { Preconditions.checkArgument(!key.isEmpty()); if (key.size() == 1) { IntComparator comparator = SortUtils.getComparator(table, key); this.sortOrder = sortOn(comparator); } else { IntComparatorChain chain = SortUtils.getChain(table, key); this.sortOrder = sortOn(chain); } } /** Returns an array of integers representing the source table indexes in sorted order. */ private int[] sortOn(IntComparator rowComparator) { int[] newRows; if (hasSelection()) { newRows = this.selection.toArray(); } else { newRows = IntStream.range(0, table.rowCount()).toArray(); } IntArrays.parallelQuickSort(newRows, rowComparator); return newRows; } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy