Java tutorial
/* * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ /** * InstancesView.java * Copyright (C) 2016 University of Waikato, Hamilton, NZ */ package adams.ml.data; import adams.core.DateFormat; import adams.core.DateUtils; import adams.core.Utils; import adams.core.exception.NotImplementedException; import adams.core.management.LocaleHelper; import adams.data.SharedStringsTable; import adams.data.spreadsheet.Cell; import adams.data.spreadsheet.Cell.ContentType; import adams.data.spreadsheet.DataRow; import adams.data.spreadsheet.HeaderRow; import adams.data.spreadsheet.Row; import adams.data.spreadsheet.RowComparator; import adams.data.spreadsheet.SpreadSheet; import adams.data.spreadsheet.SpreadSheetUtils; import adams.data.spreadsheet.SpreadSheetView; import weka.core.Attribute; import weka.core.DenseInstance; import weka.core.Instances; import weka.filters.Filter; import weka.filters.unsupervised.attribute.Remove; import java.text.NumberFormat; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.Comparator; import java.util.HashSet; import java.util.List; import java.util.Locale; import java.util.TimeZone; /** * Provides a view of an {@link Instances} object. * * @author FracPete (fracpete at waikato dot ac dot nz) * @version $Revision$ */ public class InstancesView implements Dataset { private static final long serialVersionUID = -6570030309091506840L; /** the underlying data. */ protected Instances m_Data; /** the header row. */ protected InstancesHeaderRow m_Header; /** the shared string table. */ protected SharedStringsTable m_SharedStringsTable; /** * Initializes the view with a dummy dataset. */ public InstancesView() { this(createDummy()); } /** * Returns a dummy dataset. * * @return the dataset */ protected static Instances createDummy() { ArrayList<Attribute> atts; atts = new ArrayList<>(); atts.add(new Attribute("dummy")); return new Instances("dummy", atts, 0); } /** * Initializes the view. * * @param data the data to use */ public InstancesView(Instances data) { m_Data = data; m_SharedStringsTable = new SharedStringsTable(); m_Header = new InstancesHeaderRow(this); } /** * Returns the underlying Instances. * * @return the underlying data */ public Instances getData() { return m_Data; } /** * Turns the rowKey into a row index. * * @param rowKey the rowKey to convert * @return the row index, -1 if failed to convert */ protected int rowKeyToIndex(String rowKey) { if (Utils.isInteger(rowKey)) return Integer.parseInt(rowKey); else return -1; } /** * Turns the cellKey into a column index. * * @param cellKey the cellKey to convert * @return the column index, -1 if failed to convert */ protected int cellKeyToIndex(String cellKey) { if (Utils.isInteger(cellKey)) return Integer.parseInt(cellKey); else return -1; } /** * Ignored. * * @param comment the comment to add */ @Override public void addComment(List<String> comment) { } /** * Returns the comments. * * @return always empty */ @Override public List<String> getComments() { return new ArrayList<>(); } /** * Removes all cells, but leaves comments. */ @Override public void clear() { m_Data.clear(); } /** * Returns the header row. * * @return the row */ @Override public HeaderRow getHeaderRow() { return m_Header; } /** * Returns the name of the specified column. * * @param colIndex the index of the column * @return the name of the column */ @Override public String getColumnName(int colIndex) { return m_Data.attribute(colIndex).name(); } /** * Returns a list of the names of all columns (i.e., the content the header * row cells). * * @return the names of the columns */ @Override public List<String> getColumnNames() { List<String> result; int i; result = new ArrayList<>(); for (i = 0; i < m_Data.numAttributes(); i++) result.add(m_Data.attribute(i).name()); return result; } /** * Returns whether the spreadsheet already contains the row with the given index. * * @param rowIndex the index to look for * @return true if the row already exists */ @Override public boolean hasRow(int rowIndex) { return (rowIndex < m_Data.numInstances()); } /** * Returns whether the spreadsheet already contains the row with the given key. * * @param rowKey the key to look for * @return true if the row already exists */ @Override public boolean hasRow(String rowKey) { int row; row = rowKeyToIndex(rowKey); return (row >= 0) || (row < m_Data.numInstances()); } /** * Creates a new cell. * * @return the new instance, null in case of an instantiation error */ @Override public Cell newCell() { return null; } /** * Appends a row to the spreadsheet. * * @return the created row */ @Override public DataRow addRow() { DenseInstance inst; inst = new DenseInstance(getColumnCount()); inst.setDataset(m_Data); m_Data.add(inst); return new InstanceView(this, inst); } /** * Adds a row with the given key to the list and returns the created object. * If the row already exists, then this row is returned instead and no new * object created. * * @param rowKey the key for the row to create * @return the created row or the already existing row */ @Override public DataRow addRow(String rowKey) { throw new NotImplementedException(); } /** * Inserts a row at the specified location. * * @param index the index where to insert the row * @return the created row */ @Override public DataRow insertRow(int index) { DenseInstance inst; inst = new DenseInstance(getColumnCount()); inst.setDataset(m_Data); m_Data.add(index, inst); return new InstanceView(this, inst); } /** * Removes the specified row. * * @param rowIndex the row to remove * @return the row that was removed, null if none removed */ @Override public Row removeRow(int rowIndex) { if ((rowIndex >= 0) && (rowIndex < getRowCount())) return new InstanceView(this, m_Data.remove(rowIndex)); else return null; } /** * Removes the specified row. * * @param rowKey the row to remove * @return the row that was removed, null if none removed */ @Override public Row removeRow(String rowKey) { return removeRow(rowKeyToIndex(rowKey)); } /** * Inserts a column at the specified location. * <br><br> * Not implemented! * * @param columnIndex the position of the column * @param header the name of the column */ @Override public void insertColumn(int columnIndex, String header) { throw new NotImplementedException(); } /** * Inserts a column at the specified location. * <br><br> * Not implemented! * * @param columnIndex the position of the column * @param header the name of the column * @param initial the initial value for the cells, "null" for missing * values (in that case no cells are added) */ @Override public void insertColumn(int columnIndex, String header, String initial) { throw new NotImplementedException(); } /** * Inserts a column at the specified location. * <br><br> * Not implemented! * * @param columnIndex the position of the column * @param header the name of the column * @param initial the initial value for the cells, "null" for missing * values (in that case no cells are added) * @param forceString whether to enforce the value to be set as string */ @Override public void insertColumn(int columnIndex, String header, String initial, boolean forceString) { throw new NotImplementedException(); } /** * Removes the specified column. * <br><br> * Not implemented! * * @param columnIndex the column to remove * @return true if removed */ @Override public boolean removeColumn(int columnIndex) { throw new NotImplementedException(); } /** * Removes the specified column. * <br><br> * Not implemented! * * @param columnKey the column to remove * @return true if removed */ @Override public boolean removeColumn(String columnKey) { throw new NotImplementedException(); } /** * Returns the row associated with the given row key, null if not found. * * @param rowKey the key of the row to retrieve * @return the row or null if not found */ @Override public DataRow getRow(String rowKey) { return getRow(rowKeyToIndex(rowKey)); } /** * Returns the row at the specified index. * * @param rowIndex the 0-based index of the row to retrieve * @return the row */ @Override public DataRow getRow(int rowIndex) { if ((rowIndex >= 0) && (rowIndex < getRowCount())) return new InstanceView(this, m_Data.instance(rowIndex)); else return null; } /** * Returns the row key at the specified index. * * @param rowIndex the 0-based index of the row key to retrieve * @return the row key */ @Override public String getRowKey(int rowIndex) { return "" + rowIndex; } /** * Returns the row index of the specified row. * * @param rowKey the row identifier * @return the 0-based row index, -1 if not found */ @Override public int getRowIndex(String rowKey) { return rowKeyToIndex(rowKey); } /** * Returns the cell index of the specified cell (in the header row). * * @param cellKey the cell identifier * @return the 0-based column index, -1 if not found */ @Override public int getCellIndex(String cellKey) { return cellKeyToIndex(cellKey); } /** * Checks whether the cell with the given indices already exists. * * @param rowIndex the index of the row to look for * @param columnIndex the index of the cell in the row to look for * @return true if the cell exists */ @Override public boolean hasCell(int rowIndex, int columnIndex) { return (rowIndex >= 0) && (rowIndex < getRowCount()) && (columnIndex >= 0) && (columnIndex < getColumnCount()); } /** * Returns the corresponding cell or null if not found. * * @param rowIndex the index of the row the cell is in * @param columnIndex the column of the cell to retrieve * @return the cell or null if not found */ @Override public Cell getCell(int rowIndex, int columnIndex) { Row row; row = getRow(rowIndex); if (row != null) return row.getCell(columnIndex); else return null; } /** * Returns the position of the cell or null if not found. A position is a * combination of a number of letters (for the column) and number (for the * row). * * @param rowKey the key of the row the cell is in * @param cellKey the key of the cell to retrieve * @return the position string or null if not found */ @Override public String getCellPosition(String rowKey, String cellKey) { return SpreadSheetUtils.getCellPosition(rowKeyToIndex(rowKey), cellKeyToIndex(cellKey)); } /** * Returns a collection of all row keys. * * @return the row keys */ @Override public Collection<String> rowKeys() { List<String> result; int i; result = new ArrayList<>(); for (i = 0; i < getRowCount(); i++) result.add("" + i); return result; } /** * Returns all rows. * * @return the rows */ @Override public Collection<DataRow> rows() { List<DataRow> result; int i; result = new ArrayList<>(); for (i = 0; i < getRowCount(); i++) result.add(getRow(i)); return result; } /** * Sorts the rows according to the row keys. * <br> * Does nothing. * * @see #rowKeys() */ @Override public void sortRowKeys() { } /** * Sorts the rows according to the row keys. * <br> * Does nothing. * * @param comp the comparator to use * @see #rowKeys() */ @Override public void sortRowKeys(Comparator<String> comp) { } /** * Sorts the rows based on the values in the specified column. * <br><br> * NB: the row keys will change! * * @param index the index (0-based) of the column to sort on * @param asc wether sorting is ascending or descending * @see #sort(RowComparator) */ @Override public void sort(int index, boolean asc) { m_Data.sort(index); if (!asc) Collections.reverse(m_Data); } /** * Sorts the rows using the given comparator. * <br><br> * Not implemented. * * @param comp the row comparator to use */ @Override public void sort(RowComparator comp) { } /** * Sorts the rows using the given comparator. * <br><br> * Not implemented. * * @param comp the row comparator to use * @param unique whether to drop any duplicate rows (based on row comparator) */ @Override public void sort(RowComparator comp, boolean unique) { } /** * Returns the number of columns. * * @return the number of columns */ @Override public int getColumnCount() { return m_Data.numAttributes(); } /** * Returns the number of rows currently stored. * * @return the number of rows */ @Override public int getRowCount() { return m_Data.numInstances(); } /** * Checks whether the given column is numeric or not. Does not accept * missing values. * * @param columnIndex the index of the column to check * @return true if purely numeric * @see #getContentTypes(int) */ @Override public boolean isNumeric(int columnIndex) { return isNumeric(columnIndex, false); } /** * Checks whether the given column is numeric or not. Can accept missing * values. * * @param columnIndex the index of the column to check * @return true if purely numeric * @see #getContentTypes(int) */ @Override public boolean isNumeric(int columnIndex, boolean allowMissing) { boolean result; int i; result = (m_Data.attribute(columnIndex).type() == Attribute.NUMERIC); if (result && !allowMissing) { for (i = 0; i < m_Data.numInstances(); i++) { if (m_Data.instance(i).isMissing(columnIndex)) { result = false; break; } } } return result; } /** * Checks whether the given column is of the specific content type or not. * * @param columnIndex the index of the column to check * @param type the content type to check * @return true if column purely consists of this content type * @see #getContentType(int) */ @Override public boolean isContentType(int columnIndex, ContentType type) { Attribute att; att = m_Data.attribute(columnIndex); if ((type == ContentType.DOUBLE) && (att.type() == Attribute.NUMERIC)) return true; else if ((type == ContentType.DATETIMEMSEC) && (att.type() == Attribute.DATE)) return true; else if ((type == ContentType.STRING) && (att.type() == Attribute.NOMINAL)) return true; else if ((type == ContentType.STRING) && (att.type() == Attribute.STRING)) return true; return false; } /** * Returns the pure content type of the given column, if available. * * @param columnIndex the index of the column to check * @return the content type that this column consists of solely, null if mixed */ @Override public ContentType getContentType(int columnIndex) { Collection<ContentType> types; types = getContentTypes(columnIndex); if (types.size() == 1) return types.iterator().next(); else return null; } /** * Returns the all content types of the given column, if available. * * @param columnIndex the index of the column to check * @return the content types that this column consists of */ @Override public Collection<ContentType> getContentTypes(int columnIndex) { List<ContentType> result; Attribute att; int i; result = new ArrayList<>(); att = m_Data.attribute(columnIndex); if (att.type() == Attribute.NUMERIC) result.add(ContentType.DOUBLE); else if (att.type() == Attribute.DATE) result.add(ContentType.DATETIMEMSEC); else if (att.type() == Attribute.NOMINAL) result.add(ContentType.STRING); else if (att.type() == Attribute.STRING) result.add(ContentType.STRING); // check for missing for (i = 0; i < m_Data.numInstances(); i++) { if (m_Data.instance(i).isMissing(columnIndex)) { result.add(ContentType.MISSING); break; } } return result; } /** * Returns the unique string values of the specified column. The returned * list is sorted. * * @param colKey the column to retrieve the values for * @return the sorted, list of unique values */ @Override public List<String> getCellValues(String colKey) { return getCellValues(cellKeyToIndex(colKey)); } /** * Returns the unique string values of the specified column. The returned * list is sorted. * * @param colIndex the column to retrieve the values for * @return the sorted, list of unique values */ @Override public List<String> getCellValues(int colIndex) { List<String> result; HashSet<String> values; int i; Cell cell; result = new ArrayList<>(); values = new HashSet<>(); for (i = 0; i < getRowCount(); i++) { cell = getCell(i, colIndex); if ((cell != null) && !cell.isMissing()) values.add(cell.getContent()); } result.addAll(values); Collections.sort(result); return result; } /** * Compares the header of this spreadsheet with the other one. * * @param other the other spreadsheet to compare with * @return null if equal, otherwise details what differs */ @Override public String equalsHeader(SpreadSheet other) { if (other instanceof InstancesView) return m_Data.equalHeadersMsg(((InstancesView) other).getData()); else throw new IllegalArgumentException( "Can only compare with other " + InstancesView.class.getName() + " objects!"); } /** * Returns the spreadsheet as matrix, with the header as the first row. * Missing values are represented as null values. * * @return the row-wise matrix */ @Override public Object[][] toMatrix() { Object[][] result; int r; int c; Row row; Cell cell; result = new Object[getRowCount() + 1][getColumnCount()]; // header for (c = 0; c < getColumnCount(); c++) result[0][c] = m_Data.attribute(c).name(); // data for (r = 0; r < getRowCount(); r++) { row = getRow(r); for (c = 0; c < getColumnCount(); c++) { cell = row.getCell(c); if ((cell == null) || cell.isMissing()) result[r + 1][c] = null; else result[r + 1][c] = cell.getNative(); } } return result; } /** * Removes all cells marked "missing". * * @return true if any cell was removed */ @Override public boolean removeMissing() { return false; } /** * Returns the table for shared strings. * * @return the table */ @Override public SharedStringsTable getSharedStringsTable() { return m_SharedStringsTable; } /** * Sets whether parsing of dates is to be lenient or not. * * @param value if true lenient parsing is used, otherwise not * @see SimpleDateFormat#setLenient(boolean) */ @Override public void setDateLenient(boolean value) { } /** * Returns whether the parsing of dates is lenient or not. * * @return true if parsing is lenient * @see SimpleDateFormat#isLenient() */ @Override public boolean isDateLenient() { return false; } /** * Sets whether parsing of date/times is to be lenient or not. * * @param value if true lenient parsing is used, otherwise not * @see SimpleDateFormat#setLenient(boolean) */ @Override public void setDateTimeLenient(boolean value) { } /** * Returns whether the parsing of date/times is lenient or not. * * @return true if parsing is lenient * @see SimpleDateFormat#isLenient() */ @Override public boolean isDateTimeLenient() { return false; } /** * Sets whether parsing of date/time mses is to be lenient or not. * * @param value if true lenient parsing is used, otherwise not * @see SimpleDateFormat#setLenient(boolean) */ @Override public void setDateTimeMsecLenient(boolean value) { } /** * Returns whether the parsing of date/time msecs is lenient or not. * * @return true if parsing is lenient * @see SimpleDateFormat#isLenient() */ @Override public boolean isDateTimeMsecLenient() { return false; } /** * Sets whether parsing of times is to be lenient or not. * * @param value if true lenient parsing is used, otherwise not */ @Override public void setTimeLenient(boolean value) { } /** * Returns whether the parsing of times is lenient or not. * * @return true if parsing is lenient */ @Override public boolean isTimeLenient() { return false; } /** * Sets whether parsing of times/msec is to be lenient or not. * * @param value if true lenient parsing is used, otherwise not */ @Override public void setTimeMsecLenient(boolean value) { } /** * Returns whether the parsing of times/msec is lenient or not. * * @return true if parsing is lenient */ @Override public boolean isTimeMsecLenient() { return false; } /** * Sets the timezone to use. * * @param value the new timezone * @see SimpleDateFormat#setTimeZone(TimeZone) */ @Override public void setTimeZone(TimeZone value) { } /** * Returns the currently used timezone. * * @return the current timezone * @see SimpleDateFormat#getTimeZone() */ @Override public TimeZone getTimeZone() { return null; } /** * Sets the locale. Used in formatting/parsing numbers. * * @param value the locale to use */ @Override public void setLocale(Locale value) { } /** * Returns the current locale. * * @return the locale */ @Override public Locale getLocale() { return null; } /** * Triggers all formula cells to recalculate their values. */ @Override public void calculate() { } /** * Puts the content of the provided spreadsheet on the right. * <br><br> * Not implemented! * * @param other the spreadsheet to merge with */ @Override public void mergeWith(SpreadSheet other) { throw new NotImplementedException(); } /** * Clears this spreadsheet and copies all the data from the given one. * * @param sheet the data to copy */ @Override public void assign(SpreadSheet sheet) { if (sheet instanceof InstancesView) { m_Data = ((InstancesView) sheet).getData(); m_Header = new InstancesHeaderRow(this); } else { throw new IllegalArgumentException("Other spreadsheet can only be " + InstancesView.class.getName()); } } /** * Sets the default data row class to use. * Must implement {@link DataRow}. * * @param cls the class, null resets it to the default one * @throws IllegalArgumentException if class does not implement {@link DataRow} */ @Override public void setDataRowClass(Class cls) { } /** * Returns the class used for rows. * * @return the class */ @Override public Class getDataRowClass() { return InstanceView.class; } /** * Returns a new instance. * * @return the new instance, null if failed to create new instance */ @Override public SpreadSheet newInstance() { return null; } /** * Returns a clone of itself. * * @return the clone */ @Override public Dataset getClone() { return new InstancesView(m_Data); } /** * Returns the a spreadsheet with the same header and comments. * * @return the spreadsheet */ @Override public Dataset getHeader() { Instances data; data = new Instances(m_Data); return new InstancesView(data); } /** * Returns the date formatter. * * @return the formatter * @see DateUtils#getDateFormatter() */ @Override public DateFormat getDateFormat() { return DateUtils.getDateFormatter(); } /** * Returns the date/time formatter. * * @return the formatter * @see DateUtils#getTimestampFormatter() */ @Override public DateFormat getDateTimeFormat() { return DateUtils.getTimestampFormatter(); } /** * Returns the date/time msec formatter. * * @return the formatter * @see DateUtils#getTimestampFormatterMsecs() */ @Override public DateFormat getDateTimeMsecFormat() { return DateUtils.getTimestampFormatterMsecs(); } /** * Returns the time formatter. * * @return the formatter * @see DateUtils#getTimeFormatter() */ @Override public DateFormat getTimeFormat() { return DateUtils.getTimeFormatter(); } /** * Returns the time/msec formatter. * * @return the formatter * @see DateUtils#getTimeFormatterMsecs() */ @Override public DateFormat getTimeMsecFormat() { return DateUtils.getTimeFormatterMsecs(); } /** * Returns the number formatter. * * @return the formatter */ @Override public NumberFormat getNumberFormat() { return LocaleHelper.getSingleton().getNumberFormat(LocaleHelper.getSingleton().getDefault()); } /** * Sets the name of the spreadsheet. * * @param value the name */ @Override public void setName(String value) { m_Data.setRelationName(value); } /** * Returns the name of the spreadsheet. * * @return the name, can be null */ @Override public String getName() { return m_Data.relationName(); } /** * Returns whether the spreadsheet has a name. * * @return true if the spreadsheet is named */ @Override public boolean hasName() { return true; } /** * Adds the comment to the internal list of comments. * If the comment contains newlines, then it gets automatically split * into multiple lines and added one by one. * * @param comment the comment to add */ @Override public void addComment(String comment) { } /** * Returns the index of the column using the specified name. * * @param name the name of the column to locate * @return the index, -1 if failed to locate */ @Override public int indexOfColumn(String name) { if (m_Data.attribute(name) != null) return m_Data.attribute(name).index(); else return -1; } /** * Removes all set class attributes. */ @Override public void removeClassAttributes() { m_Data.setClassIndex(-1); } /** * Returns whether the specified column is a class attribute. * * @param colKey they key of the column to query * @return true if column a class attribute */ @Override public boolean isClassAttribute(String colKey) { int col; col = cellKeyToIndex(colKey); return (col > -1) && (m_Data.classIndex() == col); } /** * Returns whether the specified column is a class attribute. * * @param name they name of the column to query * @return true if column a class attribute */ @Override public boolean isClassAttributeByName(String name) { Attribute att; att = m_Data.attribute(name); return (att != null) && (att.index() == m_Data.classIndex()); } /** * Returns whether the specified column is a class attribute. * * @param colIndex they index of the column to query * @return true if column a class attribute */ @Override public boolean isClassAttribute(int colIndex) { return (colIndex > -1) && (colIndex == m_Data.classIndex()); } /** * Sets the class attribute status for a column. * * @param colKey the column to set the class attribute status for * @param isClass if true then the column will be flagged as class * attribute, otherwise the flag will get removed * @return true if successfully updated */ @Override public boolean setClassAttribute(String colKey, boolean isClass) { return setClassAttribute(cellKeyToIndex(colKey), isClass); } /** * Sets the class attribute status for a column. * * @param name the name of the column to set the class attribute status for * @param isClass if true then the column will be flagged as class * attribute, otherwise the flag will get removed * @return true if successfully updated */ @Override public boolean setClassAttributeByName(String name, boolean isClass) { Attribute att; att = m_Data.attribute(name); return (att != null) && setClassAttribute(att.index(), isClass); } /** * Sets the class attribute status for a column. * * @param colIndex the column to set the class attribute status for * @param isClass if true then the column will be flagged as class * attribute, otherwise the flag will get removed * @return true if successfully updated */ @Override public boolean setClassAttribute(int colIndex, boolean isClass) { if (colIndex > -1) { if (isClass) { m_Data.setClassIndex(colIndex); return true; } else { if (m_Data.classIndex() > -1) { if (m_Data.classIndex() == colIndex) { m_Data.setClassIndex(-1); return true; } } } } return false; } /** * Returns all the class attributes that are currently set. * * @return the column keys of class attributes (not ordered) */ @Override public String[] getClassAttributeKeys() { if (m_Data.classIndex() == -1) return new String[0]; else return new String[] { "" + m_Data.classIndex() }; } /** * Returns all the class attributes that are currently set. * * @return the column names of class attributes (not ordered) */ @Override public String[] getClassAttributeNames() { if (m_Data.classIndex() == -1) return new String[0]; else return new String[] { m_Data.classAttribute().name() }; } /** * Returns all the class attributes that are currently set. * * @return the indices of class attributes (sorted asc) */ @Override public int[] getClassAttributeIndices() { if (m_Data.classIndex() == -1) return new int[0]; else return new int[] { m_Data.classIndex() }; } /** * Returns a spreadsheet containing only the input columns, not class * columns. * * @return the input features, null if data conists only of class columns */ @Override public SpreadSheet getInputs() { Instances data; if (m_Data.classIndex() == -1) return this; data = new Instances(m_Data); data.setClassIndex(-1); data.deleteAttributeAt(m_Data.classIndex()); return new InstancesView(data); } /** * Returns a spreadsheet containing only output columns, i.e., the class * columns. * * @return the output features, null if data has no class columns */ @Override public SpreadSheet getOutputs() { Instances data; Remove remove; if (m_Data.classIndex() == -1) return null; data = new Instances(m_Data); data.setClassIndex(-1); remove = new Remove(); remove.setAttributeIndicesArray(new int[] { m_Data.classIndex() }); remove.setInvertSelection(true); try { remove.setInputFormat(data); data = Filter.useFilter(data, remove); return new InstancesView(data); } catch (Exception e) { throw new IllegalStateException("Failed to apply Remove filter!", e); } } /** * Creates a view of the spreadsheet with the specified rows/columns. * * @param columns the columns to use, null for all * @param rows the rows to use, null for all * @return the view */ public SpreadSheetView toView(int[] rows, int[] columns) { return new SpreadSheetView(this, rows, columns); } }