001package javax.visrec.ml.data;
002
003import java.util.Collection;
004import java.util.Collections;
005import java.util.List;
006import java.util.Objects;
007import java.util.Random;
008
009/**
010 * Generic interface for all data sets for machine learning, independent of type of elements.
011 *
012 * @author Zoran Sevarac
013 * @param <E> type of data set elements
014 * @since 1.0
015 */
016public interface DataSet<E> extends Iterable<E> {
017
018    // TODO: add stream for filtering elements in data set
019
020    /**
021     * Get a collection of the items in the {@link DataSet}
022     * @return {@link Collection}
023     */
024    List<E> getItems();
025
026    /**
027     * Adds an element to this data set.
028     *
029     * @param item data set item to add to the data set
030     * @return current instance of {@link DataSet}
031     */
032    default DataSet<E> add(E item) {
033        Objects.requireNonNull(item, "Null items are not allowed in dataset");
034        getItems().add(item);
035        return this;
036    }
037
038    /**
039     * Add an existing {@link DataSet} to the current {@link DataSet}
040     * @param dataSet existing {@link DataSet}
041     * @return current instance of {@link DataSet}
042     */
043    default DataSet<E> addAll(DataSet<E> dataSet) {
044        Objects.requireNonNull(dataSet, "Dataset is null. Cannot add items from null dataset");
045        getItems().addAll(dataSet.getItems());
046        return this;
047    }
048
049    /**
050     * Get an item from the {@link DataSet}
051     * @param index index as {@code int} which corresponds with
052     *              the index of the {@link DataSet}
053     * @return item from the {@link DataSet}
054     */
055    default E get(int index) {
056        return getItems().get(index);
057    }
058
059    /**
060     * Clear items of the {@link DataSet}
061     */
062    default  void clear() {
063        getItems().clear();
064    }
065
066    /**
067     * Determines whether the {@link DataSet} is empty or not.
068     * @return {@code true} if the {@link DataSet} is empty, otherwise {@code false}
069     */
070    default boolean isEmpty() {
071        return getItems().isEmpty();
072    }
073
074    /**
075     * Get the number of elements in {@link DataSet}
076     * @return size in {@code int}
077     */
078    default int size() {
079        return getItems().size();
080    }
081
082    /**
083     * Split dataset into specified number of equally sized parts.
084     *
085     * @param numParts number of parts to be returned
086     * @return multiple {@link DataSet} in an array.
087     */
088    DataSet<E>[] split(int numParts);
089
090    /**
091     * Split dataset into specified number of equally sized parts, using specified random generator.
092     * @param numParts number of parts/subsets to return
093     * @param rnd random number generator
094     * @return multiple {@link DataSet} in an array.
095     */
096    DataSet<E>[] split(int numParts, Random rnd);
097
098    /**
099     * Split data set in two parts, one with size of specified percentage, and other with rest of the data set
100     *
101     * @param part specified percentage of the first {@link DataSet}
102     * @return multiple {@link DataSet} in an array.
103     */
104    default DataSet<E>[] split(double part) {
105        return split(part, 1-part);
106    }
107
108    /**
109     * Split data set into parts of specified sizes
110     * @param parts specific sizes of {@link DataSet}
111     * @return array of {@link DataSet}
112     */
113    DataSet<E>[] split(double... parts);
114
115    /**
116     * Split data set into parts of specified sizes using specified random generator
117     * @param rnd random generator
118     * @param parts specific sizes of {@link DataSet}
119     * @return array of {@link DataSet}
120     */
121    DataSet<E>[] split(Random rnd, double... parts);
122
123
124    /**
125     * Shuffles the data set.
126     */
127    default void shuffle() {
128        Collections.shuffle(getItems());
129    }
130
131    /**
132     * Shuffles the data set using the specified random number generator.
133     * @param rnd random generator
134     */
135    default void shuffle(Random rnd) {
136        Collections.shuffle(getItems(), rnd);
137    }
138
139//    TODO String[] getOutputLabels();
140//    TODO void setColumnNames(String[] labels);
141
142    class Column {
143        private final String name;
144        private final ColumnType type;
145        private final boolean isTarget;
146
147        public Column(String name, ColumnType type, boolean isTarget) {
148            this.name = name;
149            this.type = type;
150            this.isTarget = isTarget;
151        }
152
153        public String getName() {
154            return name;
155        }
156
157        public ColumnType getType() {
158            return type;
159        }
160
161        public boolean isTarget() {
162            return isTarget;
163        }
164    }
165
166    enum ColumnType {
167        DECIMAL, INTEGER, BINARY, STRING;
168    }
169
170}