lipdjs
Version:
A JavaScript library for reading and writing LiPD (Linked Paleo Data) files
166 lines (142 loc) • 5.09 kB
text/typescript
import { Variable } from '../variable';
import { parseVariableValues } from "../../utils/utils";
// START TYPES
interface VariableMetadata {
hasValues?: boolean;
[key: string]: any;
}
type DataFrameData = {
[K in string]: any[];
};
interface DataFrame {
data: DataFrameData;
metadata: Record<string, VariableMetadata>;
}
interface DataList {
data: any[];
metadata: VariableMetadata[];
}
// END TYPES
export class DataTable {
private variables: Variable[] = [];
// START TEMPLATE FUNCTION
/**
* Get data as a DataFrame-like structure
* @param useStandardNames Whether to use standard variable names instead of custom names
* @returns Object containing data and metadata
*/
public getDataFrame(useStandardNames: boolean = false): DataFrame {
const result: DataFrame = {
data: {},
metadata: {}
};
for (const v of this.variables) {
const name = v.getName();
if (!name) continue;
let colname = name;
const standardVar = v.getStandardVariable();
if (useStandardNames && standardVar !== null) {
const label = standardVar.getLabel();
if (label) colname = label;
}
// Get values
const values = v.getValues();
if (values) {
result.data[colname] = parseVariableValues(values);
}
// Get metadata
const varMetadata = v.toJson() as VariableMetadata;
if (varMetadata) {
// delete varMetadata.hasValues;
result.metadata[colname] = varMetadata;
delete result.metadata[colname].hasValues;
delete result.metadata[colname].values;
}
}
return result;
}
// END TEMPLATE FUNCTION
// START TEMPLATE FUNCTION
public getDataList(): DataList {
const result: DataList = {
data: [],
metadata: []
};
for (const v of this.variables) {
// Get values
const values = v.getValues();
if (values) {
result.data.push(parseVariableValues(values));
}
// Get metadata
const varMetadata = v.toJson() as VariableMetadata;
if (varMetadata) {
// delete varMetadata.hasValues;
delete varMetadata.hasValues;
delete varMetadata.values;
result.metadata.push(varMetadata);
}
}
return result;
}
// END TEMPLATE FUNCTION
// START TEMPLATE FUNCTION
/**
* Set data from a DataFrame-like structure
* @param data Object containing data and metadata
*/
public setDataFrame(data: DataFrame): void {
// Create new set of variable objects using the metadata
this.variables = [];
for (const [colname, values] of Object.entries(data.data)) {
const metadata = data.metadata[colname];
if (!metadata) continue;
const v = Variable.fromJson(metadata);
if (v) {
v.setValues(JSON.stringify(values));
this.addVariable(v);
}
}
}
// END TEMPLATE FUNCTION
// START TEMPLATE FUNCTION
/**
* Set data from a DataFrame-like structure
* @param data Object containing data and metadata
*/
public setDataList(data: DataList): void {
// Create new set of variable objects using the metadata
this.variables = [];
// Transpose the data which is currently a list of rows with each row being a list of values
// into a list of columns with each column being a list of values
const transposedData: any[][] = [];
// Initialize transposed data structure
for (let i = 0; i < data.metadata.length; i++) {
transposedData[i] = [];
}
// Transpose rows to columns
for (let rowIndex = 0; rowIndex < data.data.length; rowIndex++) {
const row = data.data[rowIndex];
for (let colIndex = 0; colIndex < row.length; colIndex++) {
if (colIndex < transposedData.length) {
transposedData[colIndex].push(row[colIndex]);
}
}
}
// Create variables from metadata and transposed data
for (let i = 0; i < data.metadata.length; i++) {
const values = transposedData[i];
const metadata = data.metadata[i];
if (!metadata) continue;
const v = Variable.fromJson(metadata);
if (v) {
v.setValues(JSON.stringify(values));
this.addVariable(v);
}
}
}
// END TEMPLATE FUNCTION
private addVariable(variable: Variable): void {
this.variables.push(variable);
}
}