
ai.h2o.mojos.runtime.frame.MojoFrameMeta Maven / Gradle / Ivy
package ai.h2o.mojos.runtime.frame;
import ai.h2o.mojos.runtime.api.MojoColumnMeta;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
/**
* MojoFrame meta data
* ===========================
*
* Container for meta data of a {@link MojoFrame}. This immutable class is used as a template for constructing
* MojoFrames in addition to providing names to the columns of an existing MojoFrame.
*/
public class MojoFrameMeta implements Serializable {
private final List columns;
private final Map columnNameToIndex = new LinkedHashMap<>();
private final Map columnToIndex = new LinkedHashMap<>();
/**
* @deprecated use {@link #MojoFrameMeta(List)}, optionally with help of {@link MojoColumnMeta#toColumns(String[], MojoColumn.Type[], MojoColumn.Kind)} instead.
*/
@Deprecated
public MojoFrameMeta(final String[] names, final MojoColumn.Type[] types) {
this(MojoColumnMeta.toColumns(names, types, MojoColumn.Kind.Output));
}
public MojoFrameMeta(final List columns) {
this.columns = columns;
int index = 0;
for (MojoColumnMeta column : columns) {
columnNameToIndex.put(column.getColumnName(), index);
columnToIndex.put(column, index);
index++;
}
}
/**
* With this constructor, the full set of columns is used but only some of them can be retrieved by name.
* @param columns -
* @param indices -
*/
public MojoFrameMeta(final List columns, Collection indices) {
this.columns = columns;
for (int index : indices) {
columnNameToIndex.put(columns.get(index).getColumnName(), index);
}
}
/**
* @param exposedColumnNames column names to convert
* @return indices
*/
public int[] namesToIndices(final String[] exposedColumnNames) {
if (exposedColumnNames == null) {
return null;
}
final int[] others;
others = new int[exposedColumnNames.length];
for (int i = 0; i < exposedColumnNames.length; i++) {
String exposedColumnName = exposedColumnNames[i];
final int index = getColumnIndex(exposedColumnName);
others[i] = index;
}
return others;
}
/**
* @return frame containing only selected indices
*/
public MojoFrameMeta subFrame(int[] indices) {
final List columns = new ArrayList<>();
for (int index : indices) {
columns.add(getColumns().get(index));
}
return new MojoFrameMeta(columns);
}
/**
* Make a MojoFrameMeta instance with no columns
*
* @return A MojoFrameMeta instance with no columns
*/
public static MojoFrameMeta getEmpty() {
return new MojoFrameMeta(Collections.emptyList());
}
/**
* Get the index of a column with the name `columnName`
*
* @param columnName The name of the column
* @return The index of the column
*/
public int getColumnIndex(String columnName) {
final Integer index = columnNameToIndex.get(columnName);
if (index == null) {
throw new IllegalArgumentException(String.format("Column '%s' was not found in this frame with %d columns.", columnName, size()));
}
return index;
}
/**
* @deprecated Lookup by name is dangerous, as names are not unique. Use {@link #indexOf(MojoColumnMeta)} instead.
*/
@Deprecated
public Integer indexOf(String columnName) {
return columnNameToIndex.get(columnName);
}
public Integer indexOf(MojoColumnMeta column) {
return columnToIndex.get(column);
}
/**
* Get the name of a column at a particular index
*
* @param index The index of the column
* @return The name of the column
*/
public String getColumnName(int index) {
return columns.get(index).getColumnName();
}
/**
* Get the type of a column at a particular index
*
* @param index The index of a column
* @return The type of the column
*/
public MojoColumn.Type getColumnType(int index) {
return columns.get(index).getColumnType();
}
/**
* Get the type of a column with the name `columnName`
*
* @param columnName The name of the column
* @return The type of the column
*/
public MojoColumn.Type getColumnType(String columnName) {
return getColumnType(getColumnIndex(columnName));
}
/**
* Checks if there exists meta data for a column with a particular name
*
* @param columnName The name of the column
* @return true if the name exists in this instance, false otherwise
*/
public boolean contains(String columnName) {
return columnNameToIndex.containsKey(columnName);
}
/**
* Get the number of columns in this instance
*
* @return The number of columns in this instance
*/
public int size() {
return columns.size();
}
protected Map getColumnNamesMap() {
return columnNameToIndex;
}
/**
* @deprecated use {@link #getColumns()} instead
*/
@Deprecated
public String[] getColumnNames() {
return columnNameToIndex.keySet().toArray(new String[0]);
}
/**
* @deprecated use {@link #getColumns()} instead
*/
@Deprecated
public MojoColumn.Type[] getColumnTypes() {
final MojoColumn.Type[] columnTypes = new MojoColumn.Type[columns.size()];
for (int i = 0; i < columnTypes.length; i++) {
columnTypes[i] = columns.get(i).getColumnType();
}
return columnTypes;
}
public List getColumns() {
return columns;
}
@Override
public String toString() {
return niceToString(columns);
}
static String niceToString(final List columns) {
final StringBuilder sb = new StringBuilder("MojoFrameMeta{cols:");
sb.append(columns.size());
final Map typestat = new LinkedHashMap<>();
for (MojoColumnMeta col : columns) {
final String key = col.getColumnType().toString();
final Integer value = typestat.get(key);
typestat.put(key, value == null ? 1 : value + 1);
}
char sep = ';';
for (Map.Entry entry : typestat.entrySet()) {
sb.append(String.format("%s%dx%s", sep, entry.getValue(), entry.getKey()));
sep = ',';
}
sb.append("}");
return sb.toString();
}
@SuppressWarnings("unused")
public static String debugIndicesToNames(List columns, int[] indices) {
return Arrays.stream(indices)
.mapToObj(index -> index < columns.size() ? columns.get(index).getColumnName() : "IndexTooBig("+index+")")
.collect(Collectors.joining(","));
}
@SuppressWarnings("unused")
public static String debugIndicesToNames(List columns, Collection indices) {
return indices.stream()
.map(index -> index < columns.size() ? columns.get(index).getColumnName() : "IndexTooBig("+index+")")
.collect(Collectors.joining(","));
}
@SuppressWarnings("unused")
public String debugIndicesToNames(int[] indices) {
return debugIndicesToNames(columns, indices);
}
}