https://github.com/janjakubnanista/downsample
Collection of several downsampling methods for time series visualisation purposes.
https://github.com/janjakubnanista/downsample
downsample downsampling-data time-series timeseries visualisation visualization
Last synced: 11 months ago
JSON representation
Collection of several downsampling methods for time series visualisation purposes.
- Host: GitHub
- URL: https://github.com/janjakubnanista/downsample
- Owner: janjakubnanista
- License: mit
- Created: 2018-07-03T09:22:50.000Z (over 7 years ago)
- Default Branch: master
- Last Pushed: 2023-01-06T05:19:22.000Z (about 3 years ago)
- Last Synced: 2025-04-02T06:07:12.022Z (11 months ago)
- Topics: downsample, downsampling-data, time-series, timeseries, visualisation, visualization
- Language: TypeScript
- Homepage:
- Size: 13.7 MB
- Stars: 94
- Watchers: 3
- Forks: 9
- Open Issues: 30
-
Metadata Files:
- Readme: README.md
- Changelog: CHANGELOG.md
- License: LICENSE
Awesome Lists containing this project
README
downsample
Downsampling methods for time series visualisation.
Installation
|
Usage
|
API
|
Demo
|
Acknowledgement
`downsample` is useful when, not extremely surprisingly, you need to downsample a numeric time series before visualizing it without losing the visual characteristics of the data.
[downsample](https://www.npmjs.com/package/downsample) is an NPM module. You can easily download it by typing something like the following in your project:
```bash
# for all the npm people out there
npm install downsample
# or if you are a fan of yarn
yarn add downsample
```
The package exports several methods for data downsampling:
- **ASAP** Automatic Smoothing for Attention Prioritization [read more here](http://futuredata.stanford.edu/asap/)
- **SMA** Simple moving average [read more here](https://en.wikipedia.org/wiki/Moving_average#Simple_moving_average)
- **LTTB** Largest triangle three buckets [read more here](https://skemman.is/bitstream/1946/15343/3/SS_MSthesis.pdf)
- **LTOB** Largest triangle one bucket [read more here](https://skemman.is/bitstream/1946/15343/3/SS_MSthesis.pdf)
- **LTD** Largest triangle dynamic [read more here](https://skemman.is/bitstream/1946/15343/3/SS_MSthesis.pdf)
You can read more about the details of these in the [API](#api) section below.
### `ASAP` :boom: *new in 1.2.0* :boom:
Automatic Smoothing for Attention Prioritization ([read more here](http://futuredata.stanford.edu/asap/)) is a smoothing rather than downsampling method - it will remove the short-term noise and reveal the large-scale deviations.
`ASAP` accepts an array of data points (see [DataPoint](#api/DataPoint)) or a `TypedArray` (see [TypedArray support](#api/TypedArray)) and a target resolution (number of output data points) as arguments. It will always return the points in `XYDataPoint` format. [See advanced API if you need to work with a custom data type](#api/createASAP).
```typescript
function ASAP(data: DataPoint[], targetResolution: number): XYDataPoint[]
```
```typescript
import { ASAP } from 'downsample';
// Or if your codebase does not supprot tree-shaking
import { ASAP } from 'downsample/methods/ASAP';
const chartWidth = 1000;
const smooth = ASAP([
[0, 1000],
[1, 1243],
// ...
], chartWidth);
```
### `SMA` :boom: *new in 1.2.0* :boom:
Simple moving average with variable slide ([read more here](https://en.wikipedia.org/wiki/Moving_average#Simple_moving_average)).
`SMA` accepts an array of data points (see [DataPoint](#api/DataPoint)) or a `TypedArray` (see [TypedArray support](#api/TypedArray)), size of a window over which to calculate average and a slide - an amount by which the window is shifted. It will always return the points in `XYDataPoint` format. [See advanced API if you need to work with a custom data type](#api/createSMA).
```typescript
function SMA(data: DataPoint[], windowSize: number, slide?: number = 1): XYDataPoint[]
```
```typescript
import { SMA } from 'downsample';
// Or if your codebase does not supprot tree-shaking
import { SMA } from 'downsample/methods/SMA';
const chartWidth = 1000;
const smooth = SMA([
[0, 1000],
[1, 1243],
// ...
], chartWidth);
```
Largest triangle three buckets ([read more here](https://skemman.is/bitstream/1946/15343/3/SS_MSthesis.pdf)). If you are looking for the best performing downsampling method then look no more!
```typescript
function LTTB(data: DataPoint[], targetResolution: number): DataPoint[]
```
`LTTB` accepts an array of data points (see [DataPoint](#api/DataPoint)) or a `TypedArray` (see [TypedArray support](#api/TypedArray)) and a target resolution (number of output data points) as arguments. [See advanced API if you need to work with a custom data type](#api/createLTTB).
The format of the data will be preserved, i.e. if passing an array of `[number, number]` data points as `data`, you will get an array of `[number, number]` on the output.
```typescript
import { LTTB } from 'downsample';
// Or if your codebase does not supprot tree-shaking
import { LTTB } from 'downsample/methods/LTTB';
const chartWidth = 1000;
const downsampled = LTTB([
[0, 1000],
[1, 1243],
// ...
], chartWidth);
```
Largest triangle one bucket ([read more here](https://skemman.is/bitstream/1946/15343/3/SS_MSthesis.pdf)). Performs only slightly worse than LTTB.
```typescript
function LTOB(data: DataPoint[], targetResolution: number): DataPoint[]
```
`LTOB` accepts an array of data points (see [DataPoint](#api/DataPoint)) or a `TypedArray` (see [TypedArray support](#api/TypedArray)) and a target resolution (number of output data points) as arguments. [See advanced API if you need to work with a custom data type](#api/createLTOB).
The format of the data will be preserved, i.e. if passing an array of `[number, number]` data points as `data`, you will get an array of `[number, number]` on the output.
```typescript
import { LTOB } from 'downsample';
// Or if your codebase does not supprot tree-shaking
import { LTOB } from 'downsample/methods/LTOB';
const chartWidth = 1000;
const downsampled = LTOB([
[0, 1000],
[1, 1243],
// ...
], chartWidth);
```
Largest triangle dynamic ([read more here](https://skemman.is/bitstream/1946/15343/3/SS_MSthesis.pdf)). The simplest downsampling method.
```typescript
function LTD(data: DataPoint[], targetResolution: number): DataPoint[]
```
`LTD` accepts an array of data points (see [DataPoint](#api/DataPoint)) or a `TypedArray` (see [TypedArray support](#api/TypedArray)) and a target resolution (number of output data points) as arguments. [See advanced API if you need to work with a custom data type](#api/createLTD).
The format of the data will be preserved, i.e. if passing an array of `[number, number]` data points as `data`, you will get an array of `[number, number]` on the output.
```typescript
import { LTD } from 'downsample';
// Or if your codebase does not supprot tree-shaking
import { LTD } from 'downsample/methods/LTD';
const chartWidth = 1000;
const downsampled = LTD([
[0, 1000],
[1, 1243],
// ...
], chartWidth);
```
Represents a data point in the input data array. These formats are currently supported:
```typescript
type DataPoint =
[number, number] |
[Date, number] |
{ x: number; y: number } |
{ x: Date; y: number } |
```
It is now possible to pass `TypedArray` data to downsampling functions. The returned type will then match the input type, e.g. if `Int16Array` is passed in, the result will be a `Int16Array`:
```typescript
const input: Int16Array = new Int16Array(...);
const result: Int16Array = LTD(input, 1000);
```
## Advanced API
All the functions above work with `DataPoint` objects as a reasonable default. If however this does not fit your needs you can create your own version of a function using a downsampling function factory.
Creates an [ASAP](#api/ASAP) smoothing function for a specific point data type `P`.
```typescript
function createASAP({
x: string | number | (point: P) => number,
y: string | number | (point: P) => number,
toPoint: (x: number, y: number) => P
}): ASAP;
```
Creates a [SMA](#api/SMA) smoothing function for a specific point data type `P`.
```typescript
function createSMA({
x: string | number | (point: P) => number,
y: string | number | (point: P) => number,
toPoint: (x: number, y: number) => P
}): SMA;
```
Creates an [LTD](#api/LTD) downsampling function for a specific point data type `P`.
```typescript
function createLTD({
x: string | number | (point: P) => number,
y: string | number | (point: P) => number
}): LTD;
```
Creates an [LTOB](#api/LTOB) downsampling function for a specific point data type `P`.
```typescript
function createLTOB({
x: string | number | (point: P) => number,
y: string | number | (point: P) => number
}): LTOB;
```
Creates an [LTTB](#api/LTTB) downsampling function for a specific point data type `P`.
```typescript
function createLTTB({
x: string | number | (point: P) => number,
y: string | number | (point: P) => number
}): LTTB;
```
There is a very minimal interactive demo app available if you want to play around with the results of downsampling. [Check it out here](https://janjakubnanista.github.io/downsample/).
The implementation of `LTD`, `LTOB` and `LTTB` is based on Sveinn Steinarsson's 2013 paper _Downsampling Time Series for
Visual Representation_ that can be found [here](https://skemman.is/bitstream/1946/15343/3/SS_MSthesis.pdf).
The implementation of `ASAP` is based on Kexin Rong's and Peter Bailis's 2017 paper. _ASAP: Prioritizing Attention via Time Series Smoothing_ that can be found [here](https://arxiv.org/pdf/1703.00983.pdf). The original code can be found [here](https://github.com/stanford-futuredata/ASAP/blob/master/ASAP-optimized.js)