https://github.com/observablehq/array
Manipulate columnar data efficiently using typed arrays.
https://github.com/observablehq/array
Last synced: 2 months ago
JSON representation
Manipulate columnar data efficiently using typed arrays.
- Host: GitHub
- URL: https://github.com/observablehq/array
- Owner: observablehq
- License: isc
- Created: 2018-06-29T15:26:11.000Z (almost 7 years ago)
- Default Branch: master
- Last Pushed: 2018-06-30T21:44:49.000Z (almost 7 years ago)
- Last Synced: 2025-04-07T09:01:35.452Z (3 months ago)
- Language: JavaScript
- Homepage: https://beta.observablehq.com/@mbostock/manipulating-flat-arrays
- Size: 82 KB
- Stars: 124
- Watchers: 9
- Forks: 7
- Open Issues: 1
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# @observablehq/array
This library provides methods for operating on columnar data represented as parallel arrays. Most operations involve computing an index—an array of integers, each in [0, *length* - 1]—and then using the index to derive new columns.
https://beta.observablehq.com/@mbostock/manipulating-flat-arrays
## Installing
Via [npm](https://www.npmjs.com/package/@observablehq/array):
```js
npm install @observablehq/array
```Via import from [unpkg](https://unpkg.com/@observablehq/array/):
```html
import {take} from "https://unpkg.com/@observablehq/array?module";
```
Via script tag from [unpkg](https://unpkg.com/@observablehq/array/):
```html
```
## API Reference
### Taking
# take(values, index) [<>](https://github.com/observablehq/array/blob/master/src/take.js "Source")
Returns a new array of values from the specified *values* array according to the specified *index* array. The returned array is the same type as the specified *values* array.
```js
take(["a", "b", "c", "d", "e", "f"], [0, 2, 0, 1]) // ["a", "c", "a", "b"]
```# taker(index) [<>](https://github.com/observablehq/array/blob/master/src/taker.js "Source")
Returns a [take](#take)-like function that, when passed an array of *values*, returns a new array of values from the specified *values* array according to the specified *index* array. The returned array is the same type as the specified *values* array.
```js
taker([0, 2, 0, 1])(["a", "b", "c", "d", "e", "f"]) // ["a", "c", "a", "b"]
```This method is often used to take multiple arrays simultaneously using [*array*.map](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array/map).
```js
letter = ["a", "b", "c", "d", "e", "f", "g"]
```
```js
name = ["Ay", "Bee", "Cee", "Dee", "Ee", "Ef", "Gee"]
```
```js
[letter, name].map(taker([2, 1, 0])) // [["c", "b", "a"], ["Cee", "Bee", "Ay"]]
```# get(i) [<>](https://github.com/observablehq/array/blob/master/src/get.js "Source")
Returns a [take](#take)-like function that, when passed an array of *values*, returns the value from the specified *values* array with the specified index *i*.
```js
get(2)(["a", "b", "c", "d", "e", "f"]) // "c"
```This method is often used to get from multiple arrays simultaneously using [*array*.map](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array/map).
```js
letter = ["a", "b", "c", "d", "e", "f", "g"]
```
```js
name = ["Ay", "Bee", "Cee", "Dee", "Ee", "Ef", "Gee"]
```
```js
[letter, name].map(get(2)) // ["c", "Cee"]
```# slice([start[, stop]]) [<>](https://github.com/observablehq/array/blob/master/src/slice.js "Source")
Returns a function that when passed an array, returns a slice of the array according to the specified *start* and *stop* index. The returned function is equivalent to calling [*array*.slice](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array/slice).
```js
slice(0, 3)(["Ay", "Bee", "Cee", "Dee", "Ee", "Ef", "Gee"]) // ["Ay", "Bee", "Cee"]
```This method is often used to take multiple arrays simultaneously using [*array*.map](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array/map).
```js
letter = ["a", "b", "c", "d", "e", "f", "g"]
```
```js
name = ["Ay", "Bee", "Cee", "Dee", "Ee", "Ef", "Gee"]
```
```js
[letter, name].map(slice(0, 3)) // [["a", "b", "c"], ["Ay", "Bee", "Cee"]]
```### Summarizing
# count(values) [<>](https://github.com/observablehq/array/blob/master/src/count.js "Source")
Returns the number of numeric values in the specified *values* array.
```js
count([1, "N/A", 2, NaN, 3]) // 3
```# counti(values, index) [<>](https://github.com/observablehq/array/blob/master/src/counti.js "Source")
Returns the number of numeric values in the subset of the specified *values* array in the specified *index* array. Equivalent to [count](#count)([take](#take)(*values*, *index*)).
```js
counti([1, "N/A", 2, NaN, 3], [0, 1, 2]) // 2
```# max(values) [<>](https://github.com/observablehq/array/blob/master/src/max.js "Source")
Returns the maximum numeric value in the specified *values* array. For the corresponding index, see [top](#top).
```js
max([1, "N/A", 2, NaN, 4.5]) // 4.5
```# maxi(values, index) [<>](https://github.com/observablehq/array/blob/master/src/maxi.js "Source")
Returns the maximum numeric value in the subset of the specified *values* array in the specified *index* array. Equivalent to [max](#max)([take](#take)(*values*, *index*)). For the corresponding index, see [topi](#topi).
```js
maxi([1, "N/A", 2.5, NaN, 4], [0, 1, 2]) // 2
```# min(values) [<>](https://github.com/observablehq/array/blob/master/src/min.js "Source")
Returns the minimum numeric value in the specified *values* array. For the corresponding index, see [bottom](#bottom).
```js
min([1, "N/A", 2, NaN, 4.5]) // 1
```# mini(values, index) [<>](https://github.com/observablehq/array/blob/master/src/mini.js "Source")
Returns the minimum numeric value in the subset of the specified *values* array in the specified *index* array. Equivalent to [min](#min)([take](#take)(*values*, *index*)).For the corresponding index, see [bottomi](#bottomi).
```js
mini([1.5, "N/A", 2, NaN, 4], [0, 1, 2]) // 1.5
```# mean(values) [<>](https://github.com/observablehq/array/blob/master/src/mean.js "Source")
Returns the arithmetic mean of the specified *values* array.
```js
mean([0, 1, 4, 8, NaN, 2]) // 3
```# meani(values, index) [<>](https://github.com/observablehq/array/blob/master/src/meani.js "Source")
Returns the arithmetic mean of the subset of the specified *values* array in the specified *index* array. Equivalent to [mean](#mean)([take](#take)(*values*, *index*)).
```js
meani([NaN, 1, 3, 8, 3], [0, 1, 2, 3]) // 4
```# median(values) [<>](https://github.com/observablehq/array/blob/master/src/median.js "Source")
Returns the median of the specified *values* array. Equivalent to [quantile](#quantile)(*values*, 0.5).
```js
median([0, 1, 4, 8, NaN, 2]) // 2
```# mediani(values, index) [<>](https://github.com/observablehq/array/blob/master/src/mediani.js "Source")
Returns the median of the subset of the specified *values* array in the specified *index* array. Equivalent to [quantile](#quantile)([take](#take)(*values*, *index*), 0.5).
```js
mediani([0, 1, 4, 8, NaN, 2], [0, 1, 2, 3]) // 2.5
```# quantile(values, p) [<>](https://github.com/observablehq/array/blob/master/src/quantile.js "Source")
Returns the *p*-quantile of the specified *values* array with the specified *p* using the [R-7 method](https://en.wikipedia.org/wiki/Quantile#Quantiles_of_a_population).
```js
quantile([0, 1, 4, 8, NaN, 2], 0.5) // 2
```# quantilei(values, index, p) [<>](https://github.com/observablehq/array/blob/master/src/quantilei.js "Source")
Returns the *p*-quantile of the subset of the specified *values* array in the specified *index* array with the specified *p* using the [R-7 method](https://en.wikipedia.org/wiki/Quantile#Quantiles_of_a_population). Equivalent to [quantile](#quantile)([take](#take)(*values*, *index*), *p*).
```js
quantilei([0, 1, 4, 8, NaN, 2], [0, 1, 2, 3], 0.5) // 2
```# sum(values) [<>](https://github.com/observablehq/array/blob/master/src/sum.js "Source")
Returns the sum of the specified *values* array.
```js
sum([0, 1, 4, 8, NaN, 2]) // 15
```# sumi(values, index) [<>](https://github.com/observablehq/array/blob/master/src/sumi.js "Source")
Returns the sum of the subset of the specified *values* array in the specified *index* array. Equivalent to [sum](#sum)([take](#take)(*values*, *index*)).
```js
sumi([0, 1, 4, 8, NaN, 2], [0, 1, 2, 3]) // 13
```### Sorting
# bottom(values, order = [ascending](#ascending)) [<>](https://github.com/observablehq/array/blob/master/src/bottom.js "Source")
Returns the index of the specified *values* array with the corresponding least value according to the specified *order* comparator.
```js
bottom(["f", "e", "d", "i", "g", "c", "h", "a", "b", "j"]) // 7
```# bottomi(values, index, order = [ascending](#ascending)) [<>](https://github.com/observablehq/array/blob/master/src/bottomi.js "Source")
Returns the index in the specified *index* array with the corresponding least value in the specified *values* array according to the specified *order* comparator.
```js
bottomi(["f", "e", "d", "i", "g", "c", "h", "a", "b", "j"], [0, 2, 4, 6]) // 2
```# bottoms(values, k = 5, order = [ascending](#ascending)) [<>](https://github.com/observablehq/array/blob/master/src/bottoms.js "Source")
Returns an array of the *k* indexes of the specified *values* array with the corresponding least values according to the specified *order* comparator.
```js
bottoms(["f", "e", "d", "i", "g", "c", "h", "a", "b", "j"], 3) // [7, 8, 5]
```# bottomsi(values, index, k = 5, order = [ascending](#ascending)) [<>](https://github.com/observablehq/array/blob/master/src/bottomsi.js "Source")
Returns an array of the *k* indexes in the specified *index* array with the corresponding least values in the specified *values* array according to the specified *order* comparator.
```js
bottomsi(["f", "e", "d", "i", "g", "c", "h", "a", "b", "j"], [0, 2, 4, 6], 2) // [2, 0]
```# sort(values, order = [ascending](#ascending)) [<>](https://github.com/observablehq/array/blob/master/src/sort.js "Source")
Returns the indexes of the specified *values* array sorted according to the specified *order* comparator and array of *values*.
```js
sort(["f", "e", "d", "i", "g", "c", "h", "a", "b", "j"]) // [7, 8, 5, 2, 1, 0, 4, 6, 3, 9]
```# sorti(values, index, order = [ascending](#ascending)) [<>](https://github.com/observablehq/array/blob/master/src/sorti.js "Source")
Returns a copy of the specified *index* array sorted according to the specified *order* comparator and array of *values*.
```js
sorti(["f", "e", "d", "i", "g", "c", "h", "a", "b", "j"], [0, 2, 4, 6]) // [2, 0, 4, 6]
```# top(values, order = [ascending](#ascending)) [<>](https://github.com/observablehq/array/blob/master/src/top.js "Source")
Returns the index of the specified *values* array with the corresponding greatest value according to the specified *order* comparator.
```js
top(["f", "e", "d", "i", "g", "c", "h", "a", "b", "j"]) // 9
```# topi(values, index, order = [ascending](#ascending)) [<>](https://github.com/observablehq/array/blob/master/src/topi.js "Source")
Returns the index in the specified *index* array with the corresponding greatest value in the specified *values* array according to the specified *order* comparator.
```js
topi(["f", "e", "d", "i", "g", "c", "h", "a", "b", "j"], [0, 2, 4, 6]) // 6
```# tops(values, k = 5, order = [ascending](#ascending)) [<>](https://github.com/observablehq/array/blob/master/src/tops.js "Source")
Returns an array of the *k* indexes of the specified *values* array with the corresponding greatest values according to the specified *order* comparator.
```js
tops(["f", "e", "d", "i", "g", "c", "h", "a", "b", "j"], 3) // [9, 3, 6]
```# topsi(values, index, k = 5, order = [ascending](#ascending)) [<>](https://github.com/observablehq/array/blob/master/src/topsi.js "Source")
Returns an array of the *k* indexes in the specified *index* array with the corresponding greatest values in the specified *values* array according to the specified *order* comparator.
```js
topsi(["f", "e", "d", "i", "g", "c", "h", "a", "b", "j"], [0, 2, 4, 6], 2) // [6, 4]
```### Arranging
# reverse(values) [<>](https://github.com/observablehq/array/blob/master/src/reverse.js "Source")
Returns a reversed copy of the specified *values* array. Like [*array*.reverse](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array/slice), but returns a copy.
# shuffle(length) [<>](https://github.com/observablehq/array/blob/master/src/shuffle.js "Source")
Returns an array of integers 0 … *length* - 1 in random order.
# shufflei(index) [<>](https://github.com/observablehq/array/blob/master/src/shufflei.js "Source")
Returns a shuffled copy of the specified *index* array.
### Filtering
# filter(values, test) [<>](https://github.com/observablehq/array/blob/master/src/filter.js "Source")
Returns an array of indexes from the specified *values* array for which the specified *test* function returned truthy. The *test* function is passed a value from the *values* array, the corresponding index, and the *values* array itself.
```js
filter(["Ay", "Bee", "Cee", "Dee", "Ee", "Ef", "Gee"], d => d.length === 2) // [0, 4, 5]
```# filteri(values, index, test) [<>](https://github.com/observablehq/array/blob/master/src/filteri.js "Source")
Returns the subset of the specified *index* for which the specified *test* function returned truthy. The *test* function is passed a value from the *values* array, the corresponding index, and the *values* array itself.
```js
filteri(["Ay", "Bee", "Cee", "Dee", "Ee", "Ef", "Gee"], [0, 1, 2, 3], d => d.length === 2) // [0]
```### Grouping
# group(values, key = [identity](#identity)[, value]) [<>](https://github.com/observablehq/array/blob/master/src/group.js "Source")
Returns a new Map where the keys of the map are computed by applying the specified *key* function to each element in the specified *values* array.
```js
name = ["Ay", "Bee", "Cee", "Dee", "Ee", "Ef", "Gee"]
```
```js
group(name, d => d.length) // {2 => ["Ay", "Ee", "Ef"], 3 => ["Bee", "Cee", "Dee", "Gee"]}
```If a *value* function is specified, it is invoked with the array of indexes for each entry in the returned map, and the returned map’s value is replaced by whatever the *value* function returns.
```js
letter = ["a", "b", "c", "d", "e", "f", "g"]
```
```js
group(name, d => d.length, i => take(letter, i)) // {2 => ["a", "e", "f"], 3 => ["b", "c", "d", "g"]}
```
```js
group(name, d => d.length, i => i.length) // {2 => 3, 3 => 4}
```# groupi(values, index, key = [identity](#identity)[, value]) [<>](https://github.com/observablehq/array/blob/master/src/groupi.js "Source")
Returns a new Map where the keys of the map are computed by applying the specified *key* function to each element in the specified *values* array present in the specified *index* array.
```js
name = ["Ay", "Bee", "Cee", "Dee", "Ee", "Ef", "Gee"]
```
```js
groupi(name, [0, 1, 2], d => d.length) // {2 => ["Ay"], 3 => ["Bee", "Cee"]}
```If a *value* function is specified, it is invoked with the array of indexes for each entry in the returned map, and the returned map’s value is replaced by whatever the *value* function returns.
```js
letter = ["a", "b", "c", "d", "e", "f", "g"]
```
```js
groupi(name, [0, 1, 2], d => d.length, i => take(letter, i)) // {2 => ["a"], 3 => ["b", "c"]}
```
```js
groupi(name, [0, 1, 2], d => d.length, i => i.length) // {2 => 1, 3 => 2}
```### Comparing
These functions are useful as the *order* argument to [sort](#sort), [top](#top) and [bottom](#bottom).
# ascending(a, b) [<>](https://github.com/observablehq/array/blob/master/src/ascending.js "Source")
Returns -1 if *a* is less than *b*, 1 if *a* is greater than *b*, 0 if *a* is equal to *b*, or NaN.
# descending(a, b) [<>](https://github.com/observablehq/array/blob/master/src/descending.js "Source")
Returns -1 if *b* is less than *a*, 1 if *b* is greater than *a*, 0 if *b* is equal to *a*, or NaN.
### Other
# identity(x) [<>](https://github.com/observablehq/array/blob/master/src/identity.js "Source")
Returns *x*.
# range([start, ]stop[, step]]) [<>](https://github.com/observablehq/array/blob/master/src/range.js "Source")
Returns an array of integers starting at the specified inclusive *start* value and stopping before the specified exclusive *stop* value. If a *start* value is not specified, it defaults to zero; if a *step* value is not specified, it defaults to 1.