d3.js の配列操作関数

  • 33
    Like
  • 0
    Comment
More than 1 year has passed since last update.

日本語訳と利用例があったらいいのになー。と思ってまとめてみた(まだ途中)。

Ordering

d3.ascending(a, b)

a < bの時は-1を返却する。
a > bの時は1を返却する。
a === bの時は0を返却する。

ascendingは昇順の自然順序な比較関数であり、昇順に要素を配置する為に、組み込みの配列ソートと組み合わせて使用​​することができる。
注意:組み込みの配列ソート順序は「自然」ではない(アルファベット順)辞書式である為、数値の配列をソートするときバグにつながる可能性がある。

console.log(d3.ascending(0,1));
// => -1
console.log(d3.ascending(0,0));
// => 0
console.log(d3.ascending(1,0));
// => 1
console.log(d3.ascending(1,1));
// => 0
console.log(d3.ascending(1,'a'));
// => NaN
var data = [10, 2, 9, 1, 5];
console.log(data.sort(d3.ascending));
// => [1, 2, 5, 9, 10]

d3.descending(a,b)

a < bの時は1を返却する。
a > bの時は-1を返却する。
a === bの時は0を返却する。

descendingは降順の「自然順序」ためのコンパレータ機能であり、降順に要素を配置する為に、組み込みの配列ソートと組み合わせて使用​​することができる。
注意:組み込みの配列ソート順序は「自然」ではない(アルファベット順)辞書式である為、数値の配列をソートするときバグにつながる可能性がある。

console.log(d3.descending(0,1));
// => 1
console.log(d3.descending(0,0));
// => 0
console.log(d3.descending(1,0));
// => -1
console.log(d3.descending(1,1));
// => 0
console.log(d3.descending(1,'a'));
// => NaN
var data = [10, 2, 9, 1, 5];
console.log(data.sort(d3.descending));
// => [10, 9, 5, 2, 1]

d3.min(array[, accessor])

自然順序を使用して、配列の最小値を返却する。
配列が空の場合はundefinedを返却する。
オプションでアクセサ関数の指定が可能で、最小値の計算前にArray.map(accessor)を呼び出すことと同義。
ビルトイン関数のMath.minとは異なり、このメソッドは、undefinedを無視する為、
これは、データの定義された領域を考慮しながら、スケールのドメインを計算することが出来る。
加えて、要素を数値の順序ではなく自然順序を使用して比較する。
例えば["20", "3"]の最大値は”20″で、[20, 3]の最小値は3

console.log(d3.min([10, 2, 9, 1, 5, undefined]));
// => 1
console.log(d3.min(['10', 2, 9, '1', 5, undefined]));
// => 1

オプションでアクセサ関数の指定が可能で、最小値の計算前にArray.map(accessor)を呼び出すことと同義。

var data = [10, 2, 9, 1, 5];
console.log(d3.min(data, function (number) {
    return number * 10;
}));
// => 10

var data = [
    {name: 'a', age: 10},
    {name: 'b', age: 2},
    {name: 'c', age: 9},
    {name: 'd', age: 1},
    {name: 'e', age: 5}
];
console.log(d3.min(data, function (e) {
    return e.age;
}));
// => 1

d3.max(array[, accessor])

挙動はd3.min(array[, accessor])と同じ。
最小値ではなく最大値を返却する。

var data = [10, 2, 9, 1, 5];
console.log(d3.max(data));
// => 10
var data = [10, 2, 9, 1, 5];
console.log(d3.max(data, function (number) {
    return number * 10;
}));
// => 100

data = [
    {name: 'a', age: 10},
    {name: 'b', age: 2},
    {name: 'c', age: 9},
    {name: 'd', age: 1},
    {name: 'e', age: 5}
];
console.log(d3.max(data, function (e) {
    return e.age;
}));
// => 10

d3.extent(array[, accessor])

自然順序を使用して配列内の最小値と最大値を返却する。
これは同時にd3.mind3.maxを呼び出すことと同義。

var data = [10, 2, 9, 1, 5];
console.log(d3.extent(data));
// => [1,10]

data = [
    {name: 'a', age: 10},
    {name: 'b', age: 2},
    {name: 'c', age: 9},
    {name: 'd', age: 1},
    {name: 'e', age: 5}
];
console.log(d3.extent(data,function(e){
    return e.age;
}));
// => [1, 10]

d3.sum(array[, accessor])

配列の合計を返却する。
配列が空である場合、0を返却する。
オプションでアクセサ関数の指定が可能で、合計を計算する前にArray.map(accessor)を呼び出すことと同義。
このメソッドでは、NaNundefinedなどの無効な値を無視して合計を計算する為、
計算可能な値のみを考慮しながらデータの計算を行うことができる。

var data = [10, 2, 9, 1, 5];
console.log(d3.sum(data));
// => 27

data = [
    {name: 'a', age: 10},
    {name: 'b', age: 2},
    {name: 'c', age: 9},
    {name: 'd', age: 1},
    {name: 'e', age: 5}
];
console.log(d3.sum(data,function(e){
    return e.age;
}));
// => 27

d3.mean(array[, accessor])

配列の平均を返却する。
配列が空である場合はundefinedを返却する。
オプションでアクセサ関数の指定が可能で、平均を計算する前にArray.map(accessor)を呼び出すことと同義。
このメソッドでは、NaNundefinedなどの無効な値を無視して合計を計算する為、
計算可能な値のみを考慮しながらデータの平均を求めることができる。

var data = [10, 2, 9, 1, 5];
console.log(d3.mean(data));
// => 5.4

data = [
    {name: 'a', age: 10},
    {name: 'b', age: 2},
    {name: 'c', age: 9},
    {name: 'd', age: 1},
    {name: 'e', age: 5}
];
console.log(d3.mean(data,function(e){
    return e.age;
}));
// => 5.4

d3.median(array[, accessor])

R-7のアルゴリズムを使用して配列の中央値を返却する。
配列が空である場合はundefinedを返却する。
オプションでアクセサ関数の指定が可能で、中央値を計算する前にArray.map(accessor)を呼び出すことと同義。
このメソッドでは、NaNundefinedなどの無効な値を無視して合計を計算する為、
計算可能な値のみを考慮しながらデータの中央値を求めることができる。

var data = [10, 2, 9, 1, 5];
console.log(d3.median(data));
// => 5

data = [
    {name: 'a', age: 10},
    {name: 'b', age: 2},
    {name: 'c', age: 9},
    {name: 'd', age: 1},
    {name: 'e', age: 5}
];
console.log(d3.median(data,function(e){
    return e.age;
}));
// => 5

data = [10.21, 2.91, 9.87, 1.41, 5.71];
console.log(d3.median(data));
// => 5.71

d3.quantile(numbers, p)

ソート済みの数値の配列と、pとして0-1までの数を指定するとP-変位?(分位数?)を返却する。
第1四分位数p=0.25を指定することで算出が可能。
第2四分位数p=0.5を指定することで算出が可能。
第3四分位数p=0.75を指定することで算出が可能。
このメソッドを呼び出す際はd3.ascendingなどによって配列内の数値が、あらかじめ昇順にソートされている必要がある。

ちなみに上記の説明で登場した5数要約の説明はこんな感じ。

データのばらつきの様子をあらわすのに、
最小値
第1四分位数(小さいほうから1/4のところのデータ)
第2四分位数(小さいほうから2/4のところのデータ、中央値と同じこと)
第3四分位数(小さいほうから3/4のところのデータ)
最大値
の5つの数を用いて表すこと。

引用元: 統計学習の指導のために(先生向け)

var data = [1, 5, 11];
// 最小値
console.log(d3.quantile(data, 0));
// => 0

// 小さい方から10%のところのデータ
console.log(d3.quantile(data, 0.1));
// => 1.7999999999999998

// 小さい方から25%のところのデータ
console.log(d3.quantile(data, 0.25));
// => 3

// 小さい方から50%のところのデータ
console.log(d3.quantile(data, 0.5));
// => 5

// 小さい方から75%のところのデータ
console.log(d3.quantile(data, 0.75));
// => 8

// 最大値
console.log(d3.quantile(data, 1));
// => 11

d3.variance(array[, accessor])

配列内の数値から不偏分散を求める。

不偏分散って何かなと思って調べてみたら説明が思いの外ダルくて後回しにした。
多分サンプル中に含まれるデータの分散をいい感じに求めるんだと思う。

内部的には

d3.variance([10, 2, 9]);

って呼ぶと

var
    a,
    d,
    m = 0
    j = 0
    s = 0;


a = data[0];
// => 10
d = a - m;
// => 10
m += d / ++j
// => 10
s += d * (a - m);
// => 0

a = data[1];
// => 2
d = a - m;
// => -8
m += d / ++j
// => 6
s += d * (a - m);
// => 32

a = data[2];
// => 9
d = a - m;
// => 3
m += d / ++j
// => 7
s += d * (a - m);
// => 38

return s / (j - 1);
// => 19

みたいな感じで不偏分散を求めるらしいが、よく解らん。。

var data = [10, 2, 9, 1, 5];
console.log(d3.variance(data));
// => 16.3

data = [
    {name: 'a', age: 10},
    {name: 'b', age: 2},
    {name: 'c', age: 9},
    {name: 'd', age: 1},
    {name: 'e', age: 5}
];
console.log(d3.variance(data,function(e){
    return e.age;
}));
// => 16.3

d3.deviation(array[, accessor])

指定された配列のバイアス補正後の分散の平方根として定義された標準偏差を返します。
だそうだ。

標本の偏りを補正した標準偏差を求める?みたいな感じかな..
統計解らな過ぎて辛い..

var data = [10, 2, 9, 1, 5];
console.log(d3.deviation(data));
// => 4.03732584763727

data = [
    {name: 'a', age: 10},
    {name: 'b', age: 2},
    {name: 'c', age: 9},
    {name: 'd', age: 1},
    {name: 'e', age: 5}
];
console.log(d3.deviation(data,function(e){
    return e.age;
}));
// => 4.03732584763727

d3.bisectLeft(array, x[, lo[, hi]])

ソートされた順序を維持するために、配列内のxの挿入ポイントの位置を特定する。
最小値挿入ポイントlo,最大値挿入ポイントhiを指定することにより配列のサブセットを指定することが可能。
デフォルトでは配列全体が挿入ポイントの計算対象になる。
xが既に配列内に存在する場合、挿入ポイントは既存エントリの前(左側)になる。
戻り値は、すでにソートされている配列をspliceする際の第一引数として利用するのに適している。
返却された挿入ポイントiを使って配列を二つに分けると、
xより小さい部分はarray.slice(lo, i)で左側に、xより大きい部分はarray.slice(i, hi)で右側になる。

var data = [1,2,3,4,5];
console.log(d3.bisectLeft(data,1.5));
// => 1

最小値挿入ポイントlo,最大値挿入ポイントhiを指定することにより配列のサブセットを指定することが可能。

var data = [1, 2, 3, 4, 5];
console.log(d3.bisectLeft(data, 0, /*lo*/1));
// => 1
console.log(d3.bisectLeft(data, 10, /*lo*/0,/*hi*/2));
// => 2

d3.bisect(array, x[, lo[, hi]]) / d3.bisectRight(array, x[, lo[, hi]])

d3.bisectLeft(array, x[, lo[, hi]])と似ているが、
xが既に配列内に存在する場合、挿入ポイントは既存エントリの後(右側)になる。
返却された挿入ポイントiを使って配列を二つに分けると、
xより小さい部分はarray.slice(lo, i)で左側に、xより大きい部分はarray.slice(i, hi)で右側になる。

var data = [1,2,3,4,5];
console.log(d3.bisectLeft(data,3));
// => 2
console.log(d3.bisect(data,3));
// => 3
console.log(d3.bisectRight(data,3));
// => 3

d3.bisector(accessor) / d3.bisector(comparator)

アクセサ関数又は比較関数を使用して二等分線を返却する。
返されたd3_bisectオブジェクトには、leftrightの両プロパティがあり、bisectLeftbisectRightに似ている。
このメソッドは、プリミティブの単純な配列に限定する代わりに、オブジェクトの配列を二分することができる。

var data = [
    {date: new Date(2011, 1, 1), value: 0.5},
    {date: new Date(2011, 2, 1), value: 0.6},
    {date: new Date(2011, 3, 1), value: 0.7},
    {date: new Date(2011, 4, 1), value: 0.8}
];
var bisect = d3.bisector(function (d) {
    return d.date;
}).right;
console.log(bisect(data, new Date(2011, 1, 2)));
// => 1

bisect = d3.bisector(function (a, b) {
    return a.date - b.date;
}).right;
console.log(bisect(data, new Date(2011, 1, 2)));
// => 4

d3.shuffle(array[, lo[, hi]])

Fisher–Yates shuffleを利用して、配列をランダム化する。
最小値シャッフルポイントlo,最小値シャッフルポイントhiを指定することにより指定したサブセットのみランダム化することが可能。

注意:
1. 破壊的なメソッドである為注意すること。
2. loarray.length以上のシャッフルポイントを指定すると無限loopする。

var data = [1,2,3,4,5];
console.log(d3.shuffle([1,2,3,4,5]));
// => [2, 1, 3, 4, 5]
console.log(d3.shuffle([1,2,3,4,5],3));
// => [1, 2, 3, 5, 4]
console.log(d3.shuffle([1,2,3,4,5],0,3));
// => [2, 3, 1, 4, 5]

Associative Arrays

d3.keys(object)

hashのプロパティ名を含む配列を返却する。
返却される配列の順序は未定義。

var data = {
    a: 10,
    b: 20,
    c: 30
};
console.log(d3.keys(data));
//=>["a", "b", "c"]

d3.values(object)

hashの値を含む配列を返却する。
返却される配列の順序は未定義。

var data = {
    a: 10,
    b: 20,
    c: 30
};
console.log(d3.values(data));
//=>[10, 20, 30]

d3.entries(object)

hashのプロパティのキーと値を含む配列を返却する。
返却される各エントリのオブジェクト形式は下記に例示した通り{key:"a",value:"10"}となる。
返却される配列の順序は未定義。

var data = {
    a: 10,
    b: 20,
    c: 30
};
console.log(d3.entries(data));
/*
 [Object, Object, Object]
 0: Object
     key: "a"
     value: 10
 1: Object
     key: "b"
     value: 20
 2: Object
     key: "c"
     value: 30
 */

Maps

d3.map([object][, key])

オブジェクトの配列から新しいmapを構築する。
key関数にて、hashのどのプロパティがkey値かが指定されている場合はmapkey値がkey関数で指定したプロパティ値となる。
key関数が指定されていない場合は配列のindexとなる。

var m = d3.map([{name: "foo"}, {name: "bar"}], function (d) {
    return d.name;
});
console.log(m);
/*
 d3_Map {_: Object}
 _: Object
     bar: Object
        name: "bar"
    foo: Object
        name: "foo"
 */

m = d3.map([{name: "foo"}, {name: "bar"}]);
console.log(m);
/*
 d3_Map {_: Object}
 _: Object
    0: Object
        name: "foo"
     1: Object
     name: "bar"
 */

map.has(key)

mapが指定されたキー文字列のエントリを持っている場合のみtrueを返却する。
注意:値がnullまたはundefinedでも指定が可能。

var m = d3.map([{name: "foo"}, {name: "bar"},{name: null}, {name: undefined}], function (d) {
    return d.name;
});

console.log(m.has('foo'));
//=> true
console.log(m.has(null));
//=> true
console.log(m.has(undefined));
//=> true
console.log(m.has('baz'));
//=> false

map.get(key)

キー文字列に紐づくエントリの値を返却する。
マップにエントリが存在しない場合にはundefinedを返却する。

var m = d3.map([{name: "foo"}, {name: "bar"},{name: null}, {name: undefined}], function (d) {
    return d.name;
});

console.log(m.get('foo'));
//=> Object {name: "foo"}
console.log(m.get(null));
//=> Object {name: null}
console.log(m.get(undefined));
//=> Object {name: undefined}
console.log(m.get('baz'));
//=> undefined

map.set(key, value)

mapに新たなエントリを追加する。
mapに同じキー文字列のエントリを持っていた場合、古いエントリが新しい値に更新される。
なおmap生成時にkey関数を渡してキー文字列に紐づく値をmapkey値とした場合も、エントリーの値を更新しただけではkey値は変わらない。

var m = d3.map([{name: "foo"}, {name: "bar"}], function (d) {
    return d.name;
});

m.set('baz',{name: "baz"});
m.set('bar',{name: "piyo"});
console.log(m);
/*
 _: Object
    bar: Object
        name: "piyo"
    baz: Object
        name: "baz"
    foo: Object
        name: "foo"
 */

map.remove(key)

キー文字列に紐づくエントリを削除する。
マップにエントリが存在しない場合には何もせずfalseを返却する。

var m = d3.map([{name: "foo"}, {name: "bar"}], function (d) {
    return d.name;
});

m.remove('foo');
m.remove('baz');

console.log(m);
/*
 _: Object
    bar: Object
        name: "bar"
 */

map.keys()

map内に存在するエントリの文字列キーを配列で返却する。
返却される配列の順序は未定義。

var m = d3.map([{name: "foo"}, {name: "bar"}], function (d) {
    return d.name;
});

console.log(m.keys());
// => ["foo", "bar"]

map.values()

map内に存在するエントリの値を配列で返却する。
返却される配列の順序は未定義。

var m = d3.map([{name: "foo"}, {name: "bar"}], function (d) {
    return d.name;
});

console.log(m.values());
/*
 0: Object
     name: "foo"
 1: Object
     name: "bar"
 */

map.entries()

map内に存在するエントリのキーと値を含む配列を返却する。
返却される各エントリのオブジェクト形式は下記に例示した通り{key:"foo",value:{name: "foo"}}となる。
返却される配列の順序は未定義。

var m = d3.map([{name: "foo"}, {name: "bar"}], function (d) {
    return d.name;
});

console.log(m.entries());
/*
 0: Object
     key: "foo"
     value: Object
         name: "foo"
 1: Object
     key: "bar"
     value: Object
        name: "bar"
 */

map.forEach(function)

mapのキー文字列とエントリを引数とした関数を、エントリ個数分繰り返し実行する。
thisの指定対象はmap自身。

var m = d3.map([{name: "foo"}, {name: "bar"}], function (d) {
    return d.name;
});

m.forEach(function (/*key*/k, /*value*/v) {
    v.name = 'update:' + k;
});
console.log(m);
/*
 _: Object
    bar: Object
        name: "update:bar"
    foo: Object
        name: "update:foo"
 */

map.empty()

mapにエントリが存在しない場合はtrue、存在する場合はfalseを返却する。

var m = d3.map([]);
console.log(m.empty());
// => true

m = d3.map([{name: "foo"}, {name: "bar"}], function (d) {
    return d.name;
});
console.log(m.empty());
// => false

map.size()

mapに存在するエントリの個数を返却する。

var m = d3.map([{name: "foo"}, {name: "bar"}], function (d) {
    return d.name;
});
console.log(m.size());
// => 2

Sets

d3.set([array])

新しい'set'を構築する。

var s = d3.set(['bar', 'baz', 'foo', 'foo']);
console.log(s);
/*
 bar: true
 baz: true
 foo: true
 */

set.has(value)

エントリがsetに含まれる場合のみtrueを返却する。

var s = d3.set(['bar', 'baz', 'foo', 'foo']);
console.log(s.has('bar'));
//=>true
console.log(s.has('buu'));
//=>false

set.add(value)

エントリをsetに追加する。

var s = d3.set(['bar', 'baz', 'foo', 'foo']);
s.add(['foo']);
s.add(['boo']);
s.add('buu');

console.log(s);
/*
 bar: true
 baz: true
 boo: true
 buu: true
 foo: true
 */

set.remove(value)

エントリをsetから削除する。

var s = d3.set(['bar', 'baz', 'foo', 'foo']);
s.remove('foo');

console.log(s);
/*
 bar: true
 baz: true
 */

set.values()

setに存在するエントリを配列にして返却する。

var s = d3.set(['bar', 'baz', 'foo', 'foo']);

console.log(s.values());
//=> ["bar", "baz", "foo"]

set.forEach(function)

setのエントリを引数とした関数を、エントリ個数分繰り返し実行する。
thisの指定対象はset自身。

var s = d3.set(['bar', 'baz', 'foo', 'foo']);

s.forEach(function(d){
    console.log(d);
});
//=>bar
//=>baz
//=>foo

set.empty()

setにエントリが存在しない場合はtrue、存在する場合はfalseを返却する。

var s = d3.set([]);
console.log(s.empty());
s = d3.set(['bar', 'baz', 'foo', 'foo']);
console.log(s.empty());

set.size()

setに存在するエントリの個数を返却する。

var s = d3.set(['bar', 'baz', 'foo', 'foo']);
console.log(s.size());
//=>3

Array Operators

d3.merge(arrays)

配列を単一の配列にマージする。
ビルトイン関数のArray.concatと同様。

注意:
本来、配列と配列を結合することを想定して作られた関数である為、例示した
ダメな例1-3
のような利用方法をすると期待値とは大幅に異なる結果が返却される。
気になるようだったらmerge.jsを確認してみるといい。

console.log(d3.merge([[1], [2, 3]]));
// => [1, 2, 3]

console.log(d3.merge([[1, 2, 3], [4, 5, 6], [7, 8, 9]]));
// => [1, 2, 3, 4, 5, 6, 7, 8, 9]

// ダメな例1
console.log(d3.merge(['1', '2', ['3','4']]));
// => ["1", "2", "3", "4"]

// ダメな例2
console.log(d3.merge(['111111', '2111', '3', ['3','4']]));
// => ["1", "1", "1", "1", "1", "1", "2", "1", "1", "1", "3", "3", "4"]

// ダメな例3
console.log(d3.merge([1, 2, 3]));
// => Uncaught RangeError: Invalid array length

d3.range([start, ]stop[, step])

等差数列を含む配列を生成する。

オプショナルな引数はstart及びstepである。
start省略時はstartはデフォルト値0をとる。
step省略時はstepはデフォルト値1をとる。

stopinfinityが指定された場合はエラーとなる。

console.log(d3.range(11));
// => [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
console.log(d3.range(1, 11));
// => [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
console.log(d3.range(0, 105, 5));
// => [0, 5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 65, 70, 75, 80, 85, 90, 95, 100]
console.log(d3.range(0.1, 1));
// => [0.1]
console.log(d3.range(0.1, Number.POSITIVE_INFINITY, 0.1));
// => Uncaught Error: infinite range

d3.permute(array, indexes)

配列から指定したインデックスより該当する値の配列を返却する。
該当する配列要素が無い場合はundefinedを返却する。

console.log(d3.permute(["a", "b", "c"], [1, 2, 0]));
// => ["b", "c", "a"]
console.log(d3.permute(["a", "b", "c"], [1, 2]));
// => ["b", "c"]
console.log(d3.permute(["a", "b", "c"], [99]));
// => [undefined]

d3.zip(arrays…)

d3.transpose(matrix)

d3.pairs(array)

Nest

d3.nest()

nest.key(function)

nest.sortKeys(comparator)

nest.sortValues(comparator)

nest.rollup(function)

nest.map(array[, mapType])

nest.entries(array)