UNPKG

data-forge

Version:

JavaScript data transformation and analysis toolkit inspired by Pandas and LINQ.

1,384 lines (1,383 loc) 147 kB
import { IIndex } from './index'; import { IDataFrame } from './dataframe'; /** * Used to configure a series. */ export interface ISeriesConfig<IndexT, ValueT> { /** * Values to put in the dataframe. * This should be array or iterable of JavaScript values. */ values?: Iterable<ValueT>; /*** * The index for the serires. * If omitted the index will default to a 0-based index. */ index?: Iterable<IndexT>; /** * Array or iterable of index,value pairs to put in the series. * If index and values are not separately specified they can be extracted * from the pairs. */ pairs?: Iterable<[IndexT, ValueT]>; /*** * Set to true when the series has been baked into memory * and does not need to be lazily evaluated. */ baked?: boolean; } /** * A user-defined callback function that can be applied to each value. */ export declare type CallbackFn<ValueT> = (value: ValueT, index: number) => void; /** * A user-defined selector function. * Transforms a value into another kind of value. */ export declare type SelectorWithIndexFn<FromT, ToT> = (value: FromT, index: number) => ToT; /** * User-defined zipper functions. * Used to 'zip together' multiple series or dataframes. */ export declare type ZipNFn<ValueT, ReturnT> = (input: ISeries<number, ValueT>) => ReturnT; export declare type Zip2Fn<T1, T2, ReturnT> = (a: T1, b: T2) => ReturnT; export declare type Zip3Fn<T1, T2, T3, ReturnT> = (a: T1, b: T2, c: T3) => ReturnT; export declare type Zip4Fn<T1, T2, T3, T4, ReturnT> = (a: T1, b: T2, c: T3, d: T4) => ReturnT; export declare type Zip5Fn<T1, T2, T3, T4, T5, ReturnT> = (a: T1, b: T2, c: T3, d: T4) => ReturnT; /** * A user-defined selector function with no index. * Transforms a value into another kind of value. */ export declare type SelectorFn<FromT, ToT> = (value: FromT) => ToT; /** * A user-defined function that joins two values and produces a result. */ export declare type JoinFn<ValueT1, ValueT2, ResultT> = (a: ValueT1, b: ValueT2) => ResultT; /** * A user-defined predicate function, returns true or false based on input. */ export declare type PredicateFn<ValueT> = (value: ValueT) => boolean; /** * A user-defined function that aggregtates a value into an accumulator * and returns the new result. */ export declare type AggregateFn<ValueT, ToT> = (accum: ToT, value: ValueT) => ToT; /** * A user-defined comparer function that Compares to values and * returns true (truthy) if they are equivalent or false (falsy) if not. */ export declare type ComparerFn<ValueT1, ValueT2> = (a: ValueT1, b: ValueT2) => boolean; export declare type SeriesConfigFn<IndexT, ValueT> = () => ISeriesConfig<IndexT, ValueT>; export declare type GapFillFn<ValueT, ResultT> = (a: ValueT, b: ValueT) => ResultT[]; /** * Represents the frequency of a type in a series or dataframe. */ export interface ITypeFrequency { /** * The name of the type. */ Type: string; /** * The frequency of the type's appearance in the series or dataframe. */ Frequency: number; } /** * Represents the frequency of a value in a series or dataframe. */ export interface IValueFrequency { /** * The value. */ Value: any; /** * The frequency of the value's appearance in the series or dataframe. */ Frequency: number; } /** * Places a value in a bucket or range of values. */ export interface IBucket { /** * The bucketed value. */ Value: number; /** * The index of the bucket that contains the value. */ Bucket: number; /** * The minimum value in the bucket. */ Min: number; /** * The mid-point value in the bucket. */ Mid: number; /** * The maximum value in the bucket. */ Max: number; } /** * Specifies where from a data window the index is pulled from: the start of the window, the end or from the middle. */ export declare enum WhichIndex { Start = "start", End = "end", } /** * Interface that represents a series. * A series contains an indexed sequence of values. * A series indexed by time is a timeseries. * * @typeparam IndexT The type to use for the index. * @typeparam ValueT The type to use for each value. */ export interface ISeries<IndexT = number, ValueT = any> extends Iterable<ValueT> { /** * Get an iterator to enumerate the values of the series. * Enumerating the iterator forces lazy evaluation to complete. * This function is automatically called by `for...of`. * * @return An iterator for the values in the series. * * @example * <pre> * * for (const value of series) { * // ... do something with the value ... * } * </pre> */ [Symbol.iterator](): Iterator<ValueT>; /** * Cast the value of the series to a new type. * This operation has no effect but to retype the values that the series contains. * * @return The same series, but with the type changed. * * @example * <pre> * * const castSeries = series.cast<SomeOtherType>(); * </pre> */ cast<NewValueT>(): ISeries<IndexT, NewValueT>; /** * Get the index for the series. * * @return The {@link Index} for the series. * * @example * <pre> * * const index = series.getIndex(); * </pre> */ getIndex(): IIndex<IndexT>; /** * Apply a new {@link Index} to the series. * * @param newIndex The new array or iterable to be the new {@link Index} of the series. Can also be a selector to choose the {@link Index} for each value in the series. * * @return Returns a new series with the specified {@link Index} attached. * * @example * <pre> * * const indexedSeries = series.withIndex([10, 20, 30]); * </pre> * * @example * <pre> * * const indexedSeries = series.withIndex(someOtherSeries); * </pre> * * @example * <pre> * * const indexedSeries = series.withIndex(value => computeIndexFromValue(value)); * </pre> * * @example * <pre> * * const indexedSeries = series.withIndex(value => value + 20); * </pre> */ withIndex<NewIndexT>(newIndex: Iterable<NewIndexT> | SelectorFn<ValueT, NewIndexT>): ISeries<NewIndexT, ValueT>; /** * Resets the {@link Index} of the series back to the default zero-based sequential integer index. * * @return Returns a new series with the {@link Index} reset to the default zero-based index. * * @example * <pre> * * const seriesWithResetIndex = series.resetIndex(); * </pre> */ resetIndex(): ISeries<number, ValueT>; /** * Merge one or more series into this series. * Values are merged by index. * Values at each index are combined into arrays in the resulting series. * * @param series... One or more other series to merge into the series. * * @returns The merged series. * * @example * <pre> * * const mergedSeries = series1.merge(series2); * </pre> * * <pre> * * const mergedSeries = series1.merge(series2, series3, etc); * </pre> */ merge<MergedValueT = any>(...args: any[]): ISeries<IndexT, MergedValueT[]>; /** * Extract values from the series as an array. * This forces lazy evaluation to complete. * * @return Returns an array of the values contained within the series. * * @example * <pre> * const values = series.toArray(); * </pre> */ toArray(): ValueT[]; /** * Retreive the index, values pairs from the series as an array. * Each pair is [index, value]. * This forces lazy evaluation to complete. * * @return Returns an array of pairs that contains the series values. Each pair is a two element array that contains an index and a value. * * @example * <pre> * const pairs = series.toPairs(); * </pre> */ toPairs(): ([IndexT, ValueT])[]; /** * Convert the series to a JavaScript object. * * @param keySelector User-defined selector function that selects keys for the resulting object. * @param valueSelector User-defined selector function that selects values for the resulting object. * * @return Returns a JavaScript object generated from the series by applying the key and value selector functions. * * @example * <pre> * * const someObject = series.toObject( * value => value, // Specify the value to use for field names in the output object. * value => value // Specify the value to use as the value for each field. * ); * </pre> */ toObject<KeyT = any, FieldT = any, OutT = any>(keySelector: (value: ValueT) => KeyT, valueSelector: (value: ValueT) => FieldT): OutT; /** * Generates a new series by repeatedly calling a user-defined selector function on each value in the original series. * * @param selector A user-defined selector function that transforms each row to create the new dataframe. * * @return Returns a new series with each value transformed by the selector function. * * @example * <pre> * * function transformValue (inputValue) { * const outputValue = { * // ... construct output value derived from input value ... * }; * * return outputValue; * } * * const transformedSeries = series.select(value => transformValue(value)); * </pre> */ select<ToT>(selector: SelectorWithIndexFn<ValueT, ToT>): ISeries<IndexT, ToT>; /** * Generates a new series by repeatedly calling a user-defined selector function on each row in the original series. * * Similar to the {@link select} function, but in this case the selector function produces a collection of output values that are flattened and merged to create the new series. * * @param selector A user-defined selector function that transforms each value into a collection of output values. * * @return Returns a new series where each value has been transformed into 0 or more new values by the selector function. * * @example * <pre> * * function produceOutputValues (inputValue) { * const outputValues = []; * while (someCondition) { * // ... generate zero or more output values ... * outputValues.push(... some generated value ...); * } * return outputValues; * } * * const modifiedSeries = series.selectMany(value => produceOutputValues(value)); * </pre> */ selectMany<ToT>(selector: SelectorWithIndexFn<ValueT, Iterable<ToT>>): ISeries<IndexT, ToT>; /** * Partition a series into a {@link Series} of *data windows*. * Each value in the new series is a chunk of data from the original series. * * @param period The number of values to include in each data window. * @param whichIndex Sets which side of the window the index comes from: start or end. Can be "start" or "end", defaults to "end". * * @return Returns a new series, each value of which is a chunk (data window) of the original series. * * @example * <pre> * * const windows = series.window(2); // Get values in pairs. * const pctIncrease = windows.select(pair => (pair.last() - pair.first()) / pair.first()); * console.log(pctIncrease.toString()); * </pre> * * @example * <pre> * * const salesDf = ... // Daily sales data. * const weeklySales = salesDf.window(7); // Partition up into weekly data sets. * console.log(weeklySales.toString()); * </pre> */ window(period: number, whichIndex?: WhichIndex): ISeries<IndexT, ISeries<IndexT, ValueT>>; /** * Partition a series into a new series of *rolling data windows*. * Each value in the new series is a rolling chunk of data from the original series. * * @param period The number of data values to include in each data window. * @param whichIndex Sets which side of the window the index comes from: start or end. Can be "start" or "end", defaults to "end". * * @return Returns a new series, each value of which is a rolling chunk of the original series. * * @example * <pre> * * const salesData = ... // Daily sales data. * const rollingWeeklySales = salesData.rollingWindow(7); // Get rolling window over weekly sales data. * console.log(rollingWeeklySales.toString()); * </pre> */ rollingWindow(period: number, whichIndex?: WhichIndex): ISeries<IndexT, ISeries<IndexT, ValueT>>; /** * Partition a series into a new series of variable-length *data windows* * where the divisions between the data chunks are * defined by a user-provided *comparer* function. * * @param comparer Function that compares two adjacent data values and returns true if they should be in the same window. * * @return Returns a new series, each value of which is a chunk of data from the original series. * * @example * <pre> * * function rowComparer (valueA, valueB) { * if (... valueA should be in the same data window as valueB ...) { * return true; * } * else { * return false; * } * }; * * const variableWindows = series.variableWindow(rowComparer); */ variableWindow(comparer: ComparerFn<ValueT, ValueT>): ISeries<number, ISeries<IndexT, ValueT>>; /** * Eliminates adjacent duplicate values. * * For each group of adjacent values that are equivalent only returns the last index/row for the group, * thus ajacent equivalent values are collapsed down to the last value. * * @param selector Optional selector function to determine the value used to compare for equivalence. * * @return Returns a new series with groups of adjacent duplicate vlaues collapsed to a single value per group. * * @example * <pre> * * const seriesWithDuplicateRowsRemoved = series.sequentialDistinct(value => value); * * // Or * const seriesWithDuplicateRowsRemoved = series.sequentialDistinct(value => value.someNestedField); * </pre> */ sequentialDistinct<ToT>(selector: SelectorFn<ValueT, ToT>): ISeries<IndexT, ValueT>; /** * Aggregate the values in the series to a single result. * * @param seed Optional seed value for producing the aggregation. * @param selector Function that takes the seed and then each value in the series and produces the aggregated value. * * @return Returns a new value that has been aggregated from the series using the 'selector' function. * * @example * <pre> * * const dailySales = ... daily sales figures for the past month ... * const totalSalesForthisMonth = dailySales.aggregate( * 0, // Seed - the starting value. * (accumulator, salesAmount) => accumulator + salesAmount // Aggregation function. * ); * </pre> * * @example * <pre> * * const totalSalesAllTime = 500; // We'll seed the aggregation with this value. * const dailySales = ... daily sales figures for the past month ... * const updatedTotalSalesAllTime = dailySales.aggregate( * totalSalesAllTime, * (accumulator, salesAmount) => accumulator + salesAmount * ); * </pre> * * @example * <pre> * * var salesDataSummary = salesData.aggregate({ * TotalSales: series => series.count(), * AveragePrice: series => series.average(), * TotalRevenue: series => series.sum(), * }); * </pre> */ aggregate<ToT = ValueT>(seedOrSelector: AggregateFn<ValueT, ToT> | ToT, selector?: AggregateFn<ValueT, ToT>): ToT; /** * Compute the absolute range of values in each period. * The range for each period is the absolute difference between largest (max) and smallest (min) values in that period. * * @param period - Period for computing the range. * @param whichIndex Sets which side of the window the index comes from: start or end. Can be "start" or "end", defaults to "end". * * @returns Returns a new series where each value indicates the absolute range of values for each period in the original series. * * @example * <pre> * * const closingPrice = ... series of closing prices for a particular stock ... * const volatility = closingPrice.amountRange(5); * </pre> */ amountRange(period: number, whichIndex?: WhichIndex): ISeries<IndexT, number>; /** * Compute the range of values in each period in proportion to the latest value. * The range for each period is the absolute difference between largest (max) and smallest (min) values in that period. * Proportions are expressed as 0-1 values. * * @param period - Period for computing the range. * @param whichIndex Sets which side of the window the index comes from: start or end. Can be "start" or "end", defaults to "end". * * @returns Returns a new series where each value indicates the proportion change from the previous number value in the original series. * * @returns Returns a new series where each value indicates the proportionate range of values for each period in the original series. * * @example * <pre> * * const closingPrice = ... series of closing prices for a particular stock ... * const proportionVolatility = closingPrice.proportionRange(5); * </pre> */ proportionRange(period: number, whichIndex?: WhichIndex): ISeries<IndexT, number>; /** * Compute the range of values in each period in proportion to the latest value. * The range for each period is the absolute difference between largest (max) and smallest (min) values in that period. * Proportions are expressed as 0-1 values. * * @param period - Period for computing the range. * @param whichIndex Sets which side of the window the index comes from: start or end. Can be "start" or "end", defaults to "end". * * @returns Returns a new series where each value indicates the proportion change from the previous number value in the original series. * * @returns Returns a new series where each value indicates the proportionate range of values for each period in the original series. * * @example * <pre> * * const closingPrice = ... series of closing prices for a particular stock ... * const percentVolatility = closingPrice.percentRange(5); * </pre> */ percentRange(period: number, whichIndex?: WhichIndex): ISeries<IndexT, number>; /** * Compute the amount of change between pairs or sets of values in the series. * * @param period Optional period for computing the change - defaults to 2. * @param whichIndex Sets which side of the window the index comes from: start or end. Can be "start" or "end", defaults to "end". * * @returns Returns a new series where each value indicates the amount of change from the previous number value in the original series. * * @example * <pre> * * const saleFigures = ... running series of daily sales figures ... * const amountChanged = salesFigures.amountChanged(); // Amount that sales has changed, day to day. * </pre> * @example * <pre> * * const saleFigures = ... running series of daily sales figures ... * const amountChanged = salesFigures.amountChanged(7); // Amount that sales has changed, week to week. * </pre> */ amountChange(period?: number, whichIndex?: WhichIndex): ISeries<IndexT, number>; /** * Compute the proportion change between pairs or sets of values in the series. * Proportions are expressed as 0-1 values. * * @param period Optional period for computing the proportion - defaults to 2. * @param whichIndex Sets which side of the window the index comes from: start or end. Can be "start" or "end", defaults to "end". * * @returns Returns a new series where each value indicates the proportion change from the previous number value in the original series. * * @example * <pre> * * const saleFigures = ... running series of daily sales figures ... * const proportionChanged = salesFigures.amountChanged(); // Proportion that sales has changed, day to day. * </pre> * @example * <pre> * * const saleFigures = ... running series of daily sales figures ... * const proportionChanged = salesFigures.amountChanged(7); // Proportion that sales has changed, week to week. * </pre> */ proportionChange(period?: number, whichIndex?: WhichIndex): ISeries<IndexT, number>; /** * Compute the percentage change between pairs or sets of values in the series. * Percentages are expressed as 0-100 values. * * @param period Optional period for computing the percentage - defaults to 2. * @param whichIndex Sets which side of the window the index comes from: start or end. Can be "start" or "end", defaults to "end". * * @returns Returns a new series where each value indicates the percent change from the previous number value in the original series. * * @example * <pre> * * const saleFigures = ... running series of daily sales figures ... * const percentChanged = salesFigures.amountChanged(); // Percent that sales has changed, day to day. * </pre> * @example * <pre> * * const saleFigures = ... running series of daily sales figures ... * const percentChanged = salesFigures.amountChanged(7); // Percent that sales has changed, week to week. * </pre> */ percentChange(period?: number, whichIndex?: WhichIndex): ISeries<IndexT, number>; /** * For each period, compute the proportion of values that are less than the last value in the period. * Proportions are expressed as 0-1 values. * * @param period Optional period for computing the proportion rank - defaults to 2. * * @returns Returns a new series where each value indicates the proportion rank value for that period. * * @example * <pre> * * const proportionRank = series.proportionRank(); * </pre> * @example * <pre> * * const proportionRank = series.proportionRank(100); * </pre> */ proportionRank(period?: number): ISeries<IndexT, number>; /** * For each period, compute the percent of values that are less than the last value in the period. * Percent are expressed as 0-100 values. * * @param period Optional period for computing the percent rank - defaults to 2. * * @returns Returns a new series where each value indicates the percent rank value for that period. * * @example * <pre> * * const percentRank = series.percentRank(); * </pre> * @example * <pre> * * const percentRank = series.percentRank(100); * </pre> */ percentRank(period?: number): ISeries<IndexT, number>; /** * Generates a cumulative sum across a series. * * @returns Returns a new series that is the cumulative sum of values across the input series. */ cumsum(): ISeries<IndexT, number>; /** * Skip a number of values in the series. * * @param numValues Number of values to skip. * * @return Returns a new series with the specified number of values skipped. * * @example * <pre> * * const seriesWithRowsSkipped = series.skip(10); // Skip 10 rows in the original series. * </pre> */ skip(numValues: number): ISeries<IndexT, ValueT>; /** * Skips values in the series while a condition evaluates to true or truthy. * * @param predicate Returns true/truthy to continue to skip values in the original series. * * @return Returns a new series with all initial sequential values removed while the predicate returned true/truthy. * * @example * <pre> * * const seriesWithRowsSkipped = series.skipWhile(salesFigure => salesFigure > 100); // Skip initial sales figure that are less than 100. * </pre> */ skipWhile(predicate: PredicateFn<ValueT>): ISeries<IndexT, ValueT>; /** * Skips values in the series untils a condition evaluates to true or truthy. * * @param predicate Return true/truthy to stop skipping values in the original series. * * @return Returns a new series with all initial sequential values removed until the predicate returned true/truthy. * * @example * <pre> * * const seriesWithRowsSkipped = series.skipUntil(salesFigure => salesFigure > 100); // Skip initial sales figures unitl we see one greater than 100. * </pre> */ skipUntil(predicate: PredicateFn<ValueT>): ISeries<IndexT, ValueT>; /** * Take a number of values from the series. * * @param numValues Number of values to take. * * @return Returns a new series with only the specified number of values taken from the original series. * * @example * <pre> * * const seriesWithRowsTaken = series.take(15); // Take only the first 15 values from the original series. * </pre> */ take(numRows: number): ISeries<IndexT, ValueT>; /** * Takes values from the series while a condition evaluates to true or truthy. * * @param predicate Returns true/truthy to continue to take values from the original series. * * @return Returns a new series with only the initial sequential values that were taken while the predicate returned true/truthy. * * @example * <pre> * * const seriesWithRowsTaken = series.takeWhile(salesFigure => salesFigure > 100); // Take only initial sales figures that are greater than 100. * </pre> */ takeWhile(predicate: PredicateFn<ValueT>): ISeries<IndexT, ValueT>; /** * Takes values from the series until a condition evaluates to true or truthy. * * @param predicate Return true/truthy to stop taking values in the original series. * * @return Returns a new series with only the initial sequential values taken until the predicate returned true/truthy. * * @example * <pre> * * const seriesWithRowsTaken = series.takeUntil(salesFigure => salesFigure > 100); // Take all initial sales figures until we see one that is greater than 100. * </pre> */ takeUntil(predicate: PredicateFn<ValueT>): ISeries<IndexT, ValueT>; /** * Count the number of values in the seriese * * @return Returns the count of all values. * * @example * <pre> * * const numValues = series.count(); * </pre> */ count(): number; /** * Get the first value of the series. * * @return Returns the first value of the series. * * @example * <pre> * * const firstValue = series.first(); * </pre> */ first(): ValueT; /** * Get the last value of the series. * * @return Returns the last value of the series. * * @example * <pre> * * const lastValue = series.last(); * </pre> */ last(): ValueT; /** * Get the value, if there is one, with the specified index. * * @param index Index to for which to retreive the value. * * @return Returns the value from the specified index in the series or undefined if there is no such index in the present in the series. * * @example * <pre> * * const value = series.at(5); // Get the value at index 5 (with a default 0-based index). * </pre> * * @example * <pre> * * const date = ... some date ... * // Retreive the value with specified date from a time-series (assuming date indexed has been applied). * const value = series.at(date); * </pre> */ at(index: IndexT): ValueT | undefined; /** * Get X value from the start of the series. * Pass in a negative value to get all values at the head except for X values at the tail. * * @param numValues Number of values to take. * * @return Returns a new series that has only the specified number of values taken from the start of the original series. * * @examples * <pre> * * const sample = series.head(10); // Take a sample of 10 values from the start of the series. * </pre> */ head(numValues: number): ISeries<IndexT, ValueT>; /** * Get X values from the end of the series. * Pass in a negative value to get all values at the tail except X values at the head. * * @param numValues Number of values to take. * * @return Returns a new series that has only the specified number of values taken from the end of the original series. * * @examples * <pre> * * const sample = series.tail(12); // Take a sample of 12 values from the end of the series. * </pre> */ tail(numValues: number): ISeries<IndexT, ValueT>; /** * Filter the series using user-defined predicate function. * * @param predicate Predicte function to filter values from the series. Returns true/truthy to keep values, or false/falsy to omit values. * * @return Returns a new series containing only the values from the original series that matched the predicate. * * @example * <pre> * * const filtered = series.where(salesFigure => salesFigure > 100); // Filter so we only have sales figures greater than 100. * </pre> */ where(predicate: PredicateFn<ValueT>): ISeries<IndexT, ValueT>; /** * Invoke a callback function for each value in the series. * * @param callback The calback function to invoke for each value. * * @return Returns the original series with no modifications. * * @example * <pre> * * series.forEach(value => { * // ... do something with the value ... * }); * </pre> */ forEach(callback: CallbackFn<ValueT>): ISeries<IndexT, ValueT>; /** * Evaluates a predicate function for every value in the series to determine * if some condition is true/truthy for **all** values in the series. * * @param predicate Predicate function that receives each value. It should returns true/truthy for a match, otherwise false/falsy. * * @return Returns true if the predicate has returned true or truthy for every value in the series, otherwise returns false. Returns false for an empty series. * * @example * <pre> * * const result = series.all(salesFigure => salesFigure > 100); // Returns true if all sales figures are greater than 100. * </pre> */ all(predicate: PredicateFn<ValueT>): boolean; /** * Evaluates a predicate function for every value in the series to determine * if some condition is true/truthy for **any** of values in the series. * * If no predicate is specified then it simply checks if the series contains more than zero values. * * @param predicate Optional predicate function that receives each value. It should return true/truthy for a match, otherwise false/falsy. * * @return Returns true if the predicate has returned truthy for any value in the series, otherwise returns false. * If no predicate is passed it returns true if the series contains any values at all. * Returns false for an empty series. * * @example * <pre> * * const result = series.any(salesFigure => salesFigure > 100); // Do we have any sales figures greater than 100? * </pre> * * @example * <pre> * * const result = series.any(); // Do we have any sales figures at all? * </pre> */ any(predicate?: PredicateFn<ValueT>): boolean; /** * Evaluates a predicate function for every value in the series to determine * if some condition is true/truthy for **none** of values in the series. * * If no predicate is specified then it simply checks if the series contains zero values. * * @param predicate Optional predicate function that receives each value. It should return true/truthy for a match, otherwise false/falsy. * * @return Returns true if the predicate has returned truthy for zero values in the series, otherwise returns false. Returns false for an empty series. * * @example * <pre> * * const result = series.none(salesFigure => salesFigure > 100); // Do we have zero sales figures greater than 100? * </pre> * * @example * <pre> * * const result = series.none(); // Do we have zero sales figures? * </pre> */ none(predicate?: PredicateFn<ValueT>): boolean; /** * Gets a new series containing all values starting at or after the specified index value. * * @param indexValue The index value at which to start the new series. * * @return Returns a new series containing all values starting at or after the specified index value. * * @example * <pre> * * const series = new Series({ * index: [0, 1, 2, 3], // This is the default index. * values: [10, 20, 30, 40], * }); * * const lastHalf = series.startAt(2); * expect(lastHalf.toArray()).to.eql([30, 40]); * </pre> * * @example * <pre> * * const timeSeries = ... a series indexed by date/time ... * * // Get all values starting at (or after) a particular date. * const result = timeSeries.startAt(new Date(2016, 5, 4)); * </pre> */ startAt(indexValue: IndexT): ISeries<IndexT, ValueT>; /** * Gets a new series containing all values up until and including the specified index value (inclusive). * * @param indexValue The index value at which to end the new series. * * @return Returns a new series containing all values up until and including the specified index value. * * @example * <pre> * * const series = new Series({ * index: [0, 1, 2, 3], // This is the default index. * values: [10, 20, 30, 40], * }); * * const firstHalf = series.endAt(1); * expect(firstHalf.toArray()).to.eql([10, 20]); * </pre> * * @example * <pre> * * const timeSeries = ... a series indexed by date/time ... * * // Get all values ending at a particular date. * const result = timeSeries.endAt(new Date(2016, 5, 4)); * </pre> */ endAt(indexValue: IndexT): ISeries<IndexT, ValueT>; /** * Gets a new series containing all values up to the specified index value (exclusive). * * @param indexValue The index value at which to end the new series. * * @return Returns a new series containing all values up to (but not including) the specified index value. * * @example * <pre> * * const series = new Series({ * index: [0, 1, 2, 3], // This is the default index. * values: [10, 20, 30, 40], * }); * * const firstHalf = series.before(2); * expect(firstHalf.toArray()).to.eql([10, 20]); * </pre> * * @example * <pre> * * const timeSeries = ... a series indexed by date/time ... * * // Get all values before the specified date. * const result = timeSeries.before(new Date(2016, 5, 4)); * </pre> */ before(indexValue: IndexT): ISeries<IndexT, ValueT>; /** * Gets a new series containing all values after the specified index value (exclusive). * * @param indexValue The index value after which to start the new series. * * @return Returns a new series containing all values after the specified index value. * * @example * <pre> * * const series = new Series({ * index: [0, 1, 2, 3], // This is the default index. * values: [10, 20, 30, 40], * }); * * const lastHalf = df.before(1); * expect(lastHalf.toArray()).to.eql([30, 40]); * </pre> * * @example * <pre> * * const timeSerie = ... a series indexed by date/time ... * * // Get all values after the specified date. * const result = timeSeries.after(new Date(2016, 5, 4)); * </pre> */ after(indexValue: IndexT): ISeries<IndexT, ValueT>; /** * Gets a new series containing all values between the specified index values (inclusive). * * @param startIndexValue The index at which to start the new series. * @param endIndexValue The index at which to end the new series. * * @return Returns a new series containing all values between the specified index values (inclusive). * * @example * <pre> * * const series = new Series({ * index: [0, 1, 2, 3, 4, 6], // This is the default index. * values: [10, 20, 30, 40, 50, 60], * }); * * const middleSection = series.between(1, 4); * expect(middleSection.toArray()).to.eql([20, 30, 40, 50]); * </pre> * * @example * <pre> * * const timeSeries = ... a series indexed by date/time ... * * // Get all values between the start and end dates (inclusive). * const result = timeSeries.after(new Date(2016, 5, 4), new Date(2016, 5, 22)); * </pre> */ between(startIndexValue: IndexT, endIndexValue: IndexT): ISeries<IndexT, ValueT>; /** * Format the series for display as a string. * This forces lazy evaluation to complete. * * @return Generates and returns a string representation of the series. * * @example * <pre> * * console.log(series.toString()); * </pre> */ toString(): string; /** * Parse a series with string values and convert it to a series with int values. * * @return Returns a new series with values parsed from strings to ints. * * @example * <pre> * * const parsed = series.parseInts(); * </pre> */ parseInts(): ISeries<IndexT, number>; /** * Parse a series with string values and convert it to a series with float values. * * @return Returns a new series with values parsed from strings to floats. * * @example * <pre> * * const parsed = series.parseFloats(); * </pre> */ parseFloats(): ISeries<IndexT, number>; /** * Parse a series with string values and convert it to a series with date values. * * @param formatString Optional formatting string for dates. * * Moment is used for date parsing. * https://momentjs.com * * @return Returns a new series with values parsed from strings to dates. * * @example * <pre> * * const parsed = series.parseDates(); * </pre> */ parseDates(formatString?: string): ISeries<IndexT, Date>; /** * Convert a series of values of different types to a series containing string values. * * @param formatString Optional formatting string for dates. * * Numeral.js is used for number formatting. * http://numeraljs.com/ * * Moment is used for date formatting. * https://momentjs.com/docs/#/parsing/string-format/ * * @return Returns a new series values converted from values to strings. * * @example * <pre> * * const result = series.toStrings("YYYY-MM-DD"); * </pre> * * @example * <pre> * * const result = series.toStrings("0.00"); * </pre> */ toStrings(formatString?: string): ISeries<IndexT, string>; /** * Forces lazy evaluation to complete and 'bakes' the series into memory. * * @return Returns a series that has been 'baked', all lazy evaluation has completed. * * @example * <pre> * * const baked = series.bake(); * </pre> */ bake(): ISeries<IndexT, ValueT>; /** * Converts (inflates) a series to a {@link DataFrame}. * * @param selector Optional user-defined selector function that transforms each value to produce the dataframe. * * @returns Returns a dataframe that was created from the original series. * * @example * <pre> * * const dataframe = series.inflate(); // Inflate a series of objects to a dataframe. * </pre> * * @example * <pre> * * const dataframe = series.inflate(value => { AColumn: value }); // Produces a dataframe with 1 column from a series of values. * </pre> * * @example * <pre> * * const dataframe = series.inflate(value => { AColumn: value.NestedValue }); // Extract a nested value and produce a dataframe from it. * </pre> */ inflate<ToT = ValueT>(selector?: SelectorWithIndexFn<ValueT, ToT>): IDataFrame<IndexT, ToT>; /** * Sum the values in a series and returns the result. * * @returns Returns the sum of the number values in the series. * * @example * <pre> * * const totalSales = salesFigures.sum(); * </pre> */ sum(): number; /** * Average the values in a series and returns the result * * @returns Returns the average of the number values in the series. * * @example * <pre> * * const averageSales = salesFigures.average(); * </pre> */ average(): number; /** * Get the median value in the series. * Note that this sorts the series, which can be expensive. * * @returns Returns the median of the values in the series. * * @example * <pre> * * const medianSales = salesFigures.median(); * </pre> */ median(): number; /** * Get the standard deviation of number values in the series. * * @returns Returns the standard deviation of the values in the series. * * @example * <pre> * * const salesStdDev = salesFigures.std(); * </pre> */ std(): number; /** * Get the min value in the series. * * @returns Returns the minimum of the number values in the series. * * @example * <pre> * * const minSales = salesFigures.min(); * </pre> */ min(): number; /** * Get the max value in the series. * * @returns Returns the maximum of the number values in the series. * * @example * <pre> * * const maxSales = salesFigures.max(); * </pre> */ max(): number; /** * Invert the sign of every number value in the series. * This assumes that the input series contains numbers. * * @returns Returns a new series with all number values inverted. * * @example * <pre> * * const inverted = series.invert(); * </pre> */ invert(): ISeries<IndexT, number>; /** * Counts the number of sequential values where the predicate evaluates to truthy. * Outputs 0 for values when the predicate evaluates to falsy. * * @param predicate User-defined function. Should evaluate to truthy to activate the counter or falsy to deactivate it. * * @returns Returns a new series that counts up the number of sequential values where the predicate evaluates to truthy. 0 values appear when the prediate evaluates to falsy. * * @example * <pre> * * const series = new Series([ 1, 10, 3, 15, 8, 5 ]); * const counted = series.counter(value => value >= 3); * console.log(counted.toString()); * </pre> */ counter(predicate: PredicateFn<ValueT>): ISeries<IndexT, number>; /** * Gets a new series in reverse order. * * @return Returns a new series that is the reverse of the original. * * @example * <pre> * * const reversed = series.reverse(); * </pre> */ reverse(): ISeries<IndexT, ValueT>; /** * Returns only the set of values in the series that are distinct. * Provide a user-defined selector to specify criteria for determining the distinctness. * This can be used to remove duplicate values from the series. * * @param selector Optional user-defined selector function that specifies the criteria used to make comparisons for duplicate values. * * @return Returns a series containing only unique values in the series. * * @example * <pre> * * const uniqueValues = series.distinct(); // Get only non-duplicated value in the series. * </pre> * * @example * <pre> * * const bucketedValues = series.distinct(value => Math.floor(value / 10)); // Lump values into buckets of 10. * </pre> */ distinct<ToT>(selector?: SelectorFn<ValueT, ToT>): ISeries<IndexT, ValueT>; /** * Collects values in the series into a new series of groups according to a user-defined selector function. * * @param selector User-defined selector function that specifies the criteriay to group by. * * @return Returns a new series of groups. Each group is a series with values that have been grouped by the 'selector' function. * * @example * <pre> * * const sales = ... product sales ... * const salesByProduct = sales.groupBy(sale => sale.ProductId); * for (const productSalesGroup of salesByProduct) { * // ... do something with each product group ... * const productId = productSalesGroup.first().ProductId; * const totalSalesForProduct = productSalesGroup.deflate(sale => sale.Amount).sum(); * console.log(totalSalesForProduct); * } * </pre> */ groupBy<GroupT>(selector: SelectorFn<ValueT, GroupT>): ISeries<number, ISeries<IndexT, ValueT>>; /** * Collects values in the series into a new series of groups based on if the values are the same or according to a user-defined selector function. * * @param selector Optional selector that specifies the criteria for grouping. * * @return Returns a new series of groups. Each group is a series with values that are the same or have been grouped by the 'selector' function. * * @example * <pre> * * // Some ultra simple stock trading strategy backtesting... * const dailyStockPrice = ... daily stock price for a company ... * const priceGroups = dailyStockPrice.groupBy(day => day.close > day.movingAverage); * for (const priceGroup of priceGroups) { * // ... do something with each stock price group ... * * const firstDay = priceGroup.first(); * if (firstDay.close > movingAverage) { * // This group of days has the stock price above its moving average. * // ... maybe enter a long trade here ... * } * else { * // This group of days has the stock price below its moving average. * // ... maybe enter a short trade here ... * } * } * </pre> */ groupSequentialBy<GroupT>(selector?: SelectorFn<ValueT, GroupT>): ISeries<number, ISeries<IndexT, ValueT>>; /** * Concatenate multiple other series onto this series. * * @param series Multiple arguments. Each can be either a series or an array of series. * * @return Returns a single series concatenated from multiple input series. * * @example * <pre> * * const concatenated = a.concat(b); * </pre> * * @example * <pre> * * const concatenated = a.concat(b, c); * </pre> * * @example * <pre> * * const concatenated = a.concat([b, c]); * </pre> * * @example * <pre> * * const concatenated = a.concat(b, [c, d]); * </pre> * * @example * <pre> *