{"id":13998527,"url":"https://github.com/janjakubnanista/downsample","last_synced_at":"2025-04-09T09:11:17.005Z","repository":{"id":38617695,"uuid":"139559309","full_name":"janjakubnanista/downsample","owner":"janjakubnanista","description":"Collection of several downsampling methods for time series visualisation purposes.","archived":false,"fork":false,"pushed_at":"2023-01-06T05:19:22.000Z","size":14321,"stargazers_count":94,"open_issues_count":30,"forks_count":9,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-04-02T06:07:12.022Z","etag":null,"topics":["downsample","downsampling-data","time-series","timeseries","visualisation","visualization"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/janjakubnanista.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2018-07-03T09:22:50.000Z","updated_at":"2025-01-29T19:56:59.000Z","dependencies_parsed_at":"2023-02-05T10:02:07.777Z","dependency_job_id":null,"html_url":"https://github.com/janjakubnanista/downsample","commit_stats":null,"previous_names":[],"tags_count":1,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/janjakubnanista%2Fdownsample","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/janjakubnanista%2Fdownsample/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/janjakubnanista%2Fdownsample/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/janjakubnanista%2Fdownsample/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/janjakubnanista","download_url":"https://codeload.github.com/janjakubnanista/downsample/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248008630,"owners_count":21032556,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["downsample","downsampling-data","time-series","timeseries","visualisation","visualization"],"created_at":"2024-08-09T19:01:45.146Z","updated_at":"2025-04-09T09:11:16.975Z","avatar_url":"https://github.com/janjakubnanista.png","language":"TypeScript","funding_links":[],"categories":["TypeScript"],"sub_categories":[],"readme":"\u003ch1 align=\"center\"\u003e\n  downsample\n\u003c/h1\u003e\n\n\u003cp align=\"center\"\u003e\n  Downsampling methods for time series visualisation.\n\u003c/p\u003e\n\n\u003c!-- The badges section --\u003e\n\u003cp align=\"center\"\u003e\n  \u003c!-- Travis CI build status --\u003e\n  \u003ca href=\"https://travis-ci.org/janjakubnanista/downsample\"\u003e\u003cimg alt=\"Build Status\" src=\"https://travis-ci.org/janjakubnanista/downsample.svg?branch=master\"/\u003e\u003c/a\u003e\n  \u003c!-- Fury.io NPM published package version --\u003e\n  \u003ca href=\"https://www.npmjs.com/package/downsample\"\u003e\u003cimg alt=\"NPM Version\" src=\"https://badge.fury.io/js/downsample.svg\"/\u003e\u003c/a\u003e\n  \u003c!-- Shields.io dev dependencies status --\u003e\n  \u003ca href=\"https://github.com/janjakubnanista/downsample/blob/master/package.json\"\u003e\u003cimg alt=\"Dev Dependency Status\" src=\"https://img.shields.io/david/dev/janjakubnanista/downsample\"/\u003e\u003c/a\u003e\n  \u003c!-- Snyk.io vulnerabilities badge --\u003e\n  \u003ca href=\"https://snyk.io/test/github/janjakubnanista/downsample\"\u003e\u003cimg alt=\"Known Vulnerabilities\" src=\"https://snyk.io/test/github/janjakubnanista/downsample/badge.svg\"/\u003e\u003c/a\u003e\n  \u003c!-- Shields.io license badge --\u003e\n  \u003ca href=\"https://github.com/janjakubnanista/downsample/blob/master/LICENSE\"\u003e\u003cimg alt=\"License\" src=\"https://img.shields.io/npm/l/downsample\"/\u003e\u003c/a\u003e\n\u003c/p\u003e\n\n\u003cp align=\"center\"\u003e\n  \u003ca href=\"#installation\"\u003eInstallation\u003c/a\u003e\n  \u003cspan\u003e|\u003c/span\u003e\n  \u003ca href=\"#usage\"\u003eUsage\u003c/a\u003e\n  \u003cspan\u003e|\u003c/span\u003e\n  \u003ca href=\"#api\"\u003eAPI\u003c/a\u003e\n  \u003cspan\u003e|\u003c/span\u003e\n  \u003ca href=\"#demo\"\u003eDemo\u003c/a\u003e\n  \u003cspan\u003e|\u003c/span\u003e\n  \u003ca href=\"#acknowledgement\"\u003eAcknowledgement\u003c/a\u003e\n\u003c/p\u003e\n\n`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.\n\n\u003ca id=\"installation\"\u003e\u003c/a\u003e\n## Installation\n\n[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:\n\n```bash\n# for all the npm people out there\nnpm install downsample\n\n# or if you are a fan of yarn\nyarn add downsample\n```\n\n\u003ca id=\"usage\"\u003e\u003c/a\u003e\n## Usage\n\nThe package exports several methods for data downsampling:\n\n- **ASAP** Automatic Smoothing for Attention Prioritization [read more here](http://futuredata.stanford.edu/asap/)\n- **SMA** Simple moving average [read more here](https://en.wikipedia.org/wiki/Moving_average#Simple_moving_average)\n- **LTTB** Largest triangle three buckets [read more here](https://skemman.is/bitstream/1946/15343/3/SS_MSthesis.pdf)\n- **LTOB** Largest triangle one bucket [read more here](https://skemman.is/bitstream/1946/15343/3/SS_MSthesis.pdf)\n- **LTD** Largest triangle dynamic [read more here](https://skemman.is/bitstream/1946/15343/3/SS_MSthesis.pdf)\n\nYou can read more about the details of these in the [API](#api) section below.\n\n\u003ca id=\"api\"\u003e\u003c/a\u003e\n## API\n\n\u003ca id=\"api/ASAP\"\u003e\u003c/a\u003e\n### `ASAP` :boom: *new in 1.2.0* :boom:\n\nAutomatic 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.\n\n`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).\n\n```typescript\nfunction ASAP(data: DataPoint[], targetResolution: number): XYDataPoint[]\n```\n\n```typescript\nimport { ASAP } from 'downsample';\n\n// Or if your codebase does not supprot tree-shaking\nimport { ASAP } from 'downsample/methods/ASAP';\n\nconst chartWidth = 1000;\nconst smooth = ASAP([\n  [0, 1000],\n  [1, 1243],\n  // ...\n], chartWidth);\n```\n\n\u003ca id=\"api/SMA\"\u003e\u003c/a\u003e\n### `SMA` :boom: *new in 1.2.0* :boom:\n\nSimple moving average with variable slide ([read more here](https://en.wikipedia.org/wiki/Moving_average#Simple_moving_average)).\n\n`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).\n\n```typescript\nfunction SMA(data: DataPoint[], windowSize: number, slide?: number = 1): XYDataPoint[]\n```\n\n```typescript\nimport { SMA } from 'downsample';\n\n// Or if your codebase does not supprot tree-shaking\nimport { SMA } from 'downsample/methods/SMA';\n\nconst chartWidth = 1000;\nconst smooth = SMA([\n  [0, 1000],\n  [1, 1243],\n  // ...\n], chartWidth);\n```\n\n\u003ca id=\"api/LTTB\"\u003e\u003c/a\u003e\n### `LTTB`\n\nLargest 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!\n\n```typescript\nfunction LTTB(data: DataPoint[], targetResolution: number): DataPoint[]\n```\n\n`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).\n\nThe 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.\n\n```typescript\nimport { LTTB } from 'downsample';\n\n// Or if your codebase does not supprot tree-shaking\nimport { LTTB } from 'downsample/methods/LTTB';\n\nconst chartWidth = 1000;\nconst downsampled = LTTB([\n  [0, 1000],\n  [1, 1243],\n  // ...\n], chartWidth);\n```\n\n\u003ca id=\"api/LTOB\"\u003e\u003c/a\u003e\n### `LTOB`\n\nLargest triangle one bucket ([read more here](https://skemman.is/bitstream/1946/15343/3/SS_MSthesis.pdf)). Performs only slightly worse than LTTB.\n\n```typescript\nfunction LTOB(data: DataPoint[], targetResolution: number): DataPoint[]\n```\n\n`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).\n\nThe 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.\n\n```typescript\nimport { LTOB } from 'downsample';\n\n// Or if your codebase does not supprot tree-shaking\nimport { LTOB } from 'downsample/methods/LTOB';\n\nconst chartWidth = 1000;\nconst downsampled = LTOB([\n  [0, 1000],\n  [1, 1243],\n  // ...\n], chartWidth);\n```\n\n\u003ca id=\"api/LTD\"\u003e\u003c/a\u003e\n### `LTD`\n\nLargest triangle dynamic ([read more here](https://skemman.is/bitstream/1946/15343/3/SS_MSthesis.pdf)). The simplest downsampling method.\n\n```typescript\nfunction LTD(data: DataPoint[], targetResolution: number): DataPoint[]\n```\n\n`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).\n\nThe 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.\n\n```typescript\nimport { LTD } from 'downsample';\n\n// Or if your codebase does not supprot tree-shaking\nimport { LTD } from 'downsample/methods/LTD';\n\nconst chartWidth = 1000;\nconst downsampled = LTD([\n  [0, 1000],\n  [1, 1243],\n  // ...\n], chartWidth);\n```\n\n\u003ca id=\"api/DataPoint\"\u003e\u003c/a\u003e\n### `DataPoint` type\n\nRepresents a data point in the input data array. These formats are currently supported:\n\n```typescript\ntype DataPoint =\n  [number, number] |\n  [Date, number] |\n  { x: number; y: number } |\n  { x: Date; y: number } |\n```\n\n\u003ca id=\"api/TypedArray\"\u003e\u003c/a\u003e\n### `TypedArray` support\n\nIt 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`:\n\n```typescript\nconst input: Int16Array = new Int16Array(...);\nconst result: Int16Array = LTD(input, 1000);\n```\n\n## Advanced API\n\nAll 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.\n\n\u003ca id=\"api/createASAP\"\u003e\u003c/a\u003e\n### `createASAP`\n\nCreates an [ASAP](#api/ASAP) smoothing function for a specific point data type `P`.\n\n```typescript\nfunction createASAP({\n  x: string | number | (point: P) =\u003e number,\n  y: string | number | (point: P) =\u003e number,\n  toPoint: (x: number, y: number) =\u003e P\n}): ASAP;\n```\n\n\u003ca id=\"api/createSMA\"\u003e\u003c/a\u003e\n### `createSMA`\n\nCreates a [SMA](#api/SMA) smoothing function for a specific point data type `P`.\n\n```typescript\nfunction createSMA({\n  x: string | number | (point: P) =\u003e number,\n  y: string | number | (point: P) =\u003e number,\n  toPoint: (x: number, y: number) =\u003e P\n}): SMA;\n```\n\n\u003ca id=\"api/createLTD\"\u003e\u003c/a\u003e\n### `createLTD`\n\nCreates an [LTD](#api/LTD) downsampling function for a specific point data type `P`.\n\n```typescript\nfunction createLTD({\n  x: string | number | (point: P) =\u003e number,\n  y: string | number | (point: P) =\u003e number\n}): LTD;\n```\n\n\u003ca id=\"api/createLTOB\"\u003e\u003c/a\u003e\n### `createLTOB`\n\nCreates an [LTOB](#api/LTOB) downsampling function for a specific point data type `P`.\n\n```typescript\nfunction createLTOB({\n  x: string | number | (point: P) =\u003e number,\n  y: string | number | (point: P) =\u003e number\n}): LTOB;\n```\n\n\u003ca id=\"api/createLTTB\"\u003e\u003c/a\u003e\n### `createLTTB`\n\nCreates an [LTTB](#api/LTTB) downsampling function for a specific point data type `P`.\n\n```typescript\nfunction createLTTB({\n  x: string | number | (point: P) =\u003e number,\n  y: string | number | (point: P) =\u003e number\n}): LTTB;\n```\n\n\u003ca id=\"demo\"\u003e\u003c/a\u003e\n## Demo\n\nThere 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/).\n\n\u003ca id=\"acknowledgement\"\u003e\u003c/a\u003e\n## Acknowledgement\n\nThe implementation of `LTD`, `LTOB` and `LTTB` is based on Sveinn Steinarsson's 2013 paper _Downsampling Time Series for\nVisual Representation_ that can be found [here](https://skemman.is/bitstream/1946/15343/3/SS_MSthesis.pdf).\n\nThe 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)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjanjakubnanista%2Fdownsample","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjanjakubnanista%2Fdownsample","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjanjakubnanista%2Fdownsample/lists"}