/*
* Apache License
* Version 2.0, January 2004
* http://www.apache.org/licenses/
*
* Copyright 2013 Aurelian Tutuianu
* Copyright 2014 Aurelian Tutuianu
* Copyright 2015 Aurelian Tutuianu
* Copyright 2016 Aurelian Tutuianu
*
* 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 rapaio.data;
import rapaio.math.linear.RM;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.stream.Collectors;
/**
* A frame which is not mapped, its values are contained in vectors.
*
* @author Aurelian Tutuianu
*/
public class SolidFrame extends AbstractFrame {
public static SolidFrame byVars(List<Var> vars) {
int rows = vars.stream().mapToInt(Var::rowCount).min().orElse(0);
return byVars(rows, vars);
}
public static SolidFrame byVars(Var... vars) {
int rows = Integer.MAX_VALUE;
for (Var var : vars) {
rows = Math.min(rows, var.rowCount());
}
if (rows == Integer.MAX_VALUE) rows = 0;
return new SolidFrame(rows, Arrays.asList(vars));
}
public static SolidFrame byVars(int rows, Var... vars) {
return byVars(rows, Arrays.asList(vars));
}
public static SolidFrame byVars(int rows, List<Var> vars) {
for (Var var : vars) {
rows = Math.min(rows, var.rowCount());
}
return new SolidFrame(rows, vars);
}
/**
* Builds a new frame with missing values, having the same variables
* as in the source frame and having given row count.
*
* @param rowCount row count
* @param src source frame
* @return new instance of solid frame built according with the source frame variables
*/
public static SolidFrame emptyFrom(Frame src, int rowCount) {
Var[] vars = new Var[src.varCount()];
for (int i = 0; i < vars.length; i++) {
vars[i] = src.var(i).type().newInstance(rowCount);
}
return SolidFrame.byVars(vars);
}
/**
* Build a frame which has only numeric columns and values are filled with 0
* (no missing values).
*
* @param rows number of getRowCount
* @param colNames column names
* @return the new built frame
*/
public static Frame matrix(int rows, String... colNames) {
return matrix(rows, Arrays.asList(colNames));
}
/**
* Build a frame which has only numeric columns and values are filled with 0
* (no missing values).
*
* @param rows number of getRowCount
* @param colNames column names
* @return the new built frame
*/
public static Frame matrix(int rows, List<String> colNames) {
List<Var> vars = new ArrayList<>();
colNames.stream().forEach(n -> vars.add(Numeric.fill(rows, 0).withName(n)));
return SolidFrame.byVars(rows, vars);
}
public static Frame matrix(RM rm, String... varNames) {
Frame df = matrix(rm.rowCount(), varNames);
for (int i = 0; i < rm.rowCount(); i++) {
for (int j = 0; j < rm.colCount(); j++) {
df.setValue(i, j, rm.get(i, j));
}
}
return df;
}
private static final long serialVersionUID = 4963238370571140813L;
private final Var[] vars;
private final HashMap<String, Integer> colIndex;
private final String[] names;
private int rows;
// public builders
private SolidFrame(int rows, List<Var> vars) {
for (Var var : vars) {
if (var instanceof MappedVar)
throw new IllegalArgumentException("Not allowed mapped vectors in solid frame");
if (var instanceof BoundVar)
throw new IllegalArgumentException("Not allowed bounded vectors in solid frame");
}
this.rows = rows;
this.vars = new Var[vars.size()];
this.colIndex = new HashMap<>();
this.names = new String[vars.size()];
for (int i = 0; i < vars.size(); i++) {
this.vars[i] = vars.get(i); //.copy();
this.colIndex.put(this.vars[i].name(), i);
this.names[i] = this.vars[i].name();
}
}
// private constructor
public static Frame matrix(RM rm, List<String> varNames) {
Frame df = matrix(rm.rowCount(), varNames);
for (int i = 0; i < rm.rowCount(); i++) {
for (int j = 0; j < rm.colCount(); j++) {
df.setValue(i, j, rm.get(i, j));
}
}
return df;
}
@Override
public int rowCount() {
return rows;
}
@Override
public int varCount() {
return vars.length;
}
@Override
public String[] varNames() {
return names;
}
@Override
public int varIndex(String name) {
if (!colIndex.containsKey(name)) {
throw new IllegalArgumentException("Invalid column name: " + name);
}
return colIndex.get(name);
}
@Override
public Var var(int col) {
if (col >= 0 && col < vars.length) {
return vars[col];
}
throw new IllegalArgumentException("Invalid column index: " + col);
}
@Override
public Var var(String name) {
return var(varIndex(name));
}
@Override
public Frame bindVars(Var... vars) {
return BoundFrame.byVars(this, BoundFrame.byVars(vars));
}
@Override
public Frame bindVars(Frame df) {
return BoundFrame.byVars(this, df);
}
@Override
public Frame mapVars(VRange range) {
List<String> varNames = range.parseVarNames(this);
List<Var> vars = varNames.stream().map(this::var).collect(Collectors.toList());
return SolidFrame.byVars(rowCount(), vars);
}
@Override
public Frame addRows(int rowCount) {
varStream().forEach(var -> var.addRows(rowCount));
this.rows += rowCount;
return this;
}
@Override
public Frame bindRows(Frame df) {
return BoundFrame.byRows(this, df);
}
@Override
public Frame mapRows(Mapping mapping) {
return MappedFrame.byRow(this, mapping);
}
}